はやさがたりない。

へっぽこぷろぐらまのメモログ

elasticsearch勉強会

elasticsearch勉強会

percolatorのユースケース

  • アラート
    インデックスが特定のクエリにマッチしたら教えてくれ。

  • 広告出稿する場合
    ユーザがサイト検索する
    アパートを検索して結果を表示するが
    新しいマッチする物件が出たら知りたい
    どのメールに通知すればいいのかみたいなのを取得して通知することができる

  • 分類
    ニュースサイトやブログがあってカテゴリわされている
    カテゴリは検索として表現できる
    ニュースに地域などの属性があれば東京のニュース一覧とかできる
    どの記事がどの地域に属するかというのを設定するにはどうしたら良いか
    percolation queryを使えばどの記事がどの地域に属するかということを簡単に設定できる。
    記事をかいてpercolationを使えばその記事のカテゴリを得られる

  • groclassificationについて
    例えば緯度経度を使って検索することもできるけど検索はめんどい
    percolationを使ってこのお地域はどの地域内にあるみたいなことも。

  • 言語の検出にも使える
    日本語は簡単だけどラテン語なんかは難しい
    特定の言語固有の単語などもあるのでこの言語にしかない単語をpercolationクエリとして
    設定しておけば言語判別できる

  • percolatorにはメタデータを設定できる
    いつそのクエリが保存されたのかなどなど
    課金している人にのみ通知したい場合、課金しているかという情報もメタデータになる
    そのメタデータによって通知の頻度を変えるとかもできる

  • ハイライトをできる
    特定のトピックについて通知をしてもらいたい場合
    トピックをpercolatorとして保存しておいて結果をハイライトできる

これが reverse search

esとRDBMSを検索するのはどう違うか

単にマッチするかどうかだけでなく、関連性も検出できる

TF-IDF
TF term frequency : 単語の出現頻度、頻度により関連性を調べられる。
IDF : どれくらいドキュメント内でレアかどうか
例えばisとかtheとか検索してもほぼ全部のドキュメントに出てくるので
あんまり関連性の重要性には寄与しない。

luceneはTF-IDF以外にもフィールドの長さを加味する
東京の本で東京について検索した場合たくさんヒットするけど
その中のタイトルでヒットすれば関連性が高いと言える

function scoreという機能を使えばドキュメント自体に
格納されていない情報も検索のタイミングでスコア算出につかうことができる
映画を検索した場合、映画のレビュー情報も算出できる。

レビューの星の数だけでソートしないほうがいいですね?
それだけでランクが決まってしまうので。
でも少しだけ順序に入れると良い。。

ホテルを検索する例
grand hotelというホテルを検索
指定した地点から1km以内がいいと指定した場合、1km以内であれば完全にマッチとするけど
そこから離れていても検査くっかに入れる
バルコニーが欲しいと指定した場合、バルコニーがなくても検索結果に入れる
でもバルコニーがあればより検索結果の上位に出すようにする
populartyというフィールド(レビュー)もランクに加味する
さらに幾分ランダムも入れる。つど発見があるように。
これらのウェイトはチューニング可能。
esは単語の頻度だけではなくいろんな情報を持っている。

aggregationについて

facetsともいう。
githubの検索結果の左側のようなやつ。
検索結果の中から検出したものでオーバービュートなる(どの言語がどれくらいあるかとか)
esを使うことで多次元の情報を見ることができる。
グラフ化するだけならRDBMSでもでk里う。

  • レコメンデーション
    音楽について、特定のアーティストをlikeしているかどうか。
    誰がどのアーティストをlikeしているのかという情報を格納する。
    レコメンドする方法としてアーティストを検索して
    さらにアーティストをlikeしている人を算出。
    でも人気は必ずしも寒冷生徒はなりません。
    termsでaggregateする代わりにsignificant term というものを使う。
    これはaggregationの一種で単に人気があるということだけでなく、
    特定のグループ内で突出しているものを調べられる。
    アーティストを、誰が、likeしているのかという情報持っているし、
    転値インデックスもあるので検出できる。
    バンドをlikeした人数と、その検索termでlikeした人数を比較すれば
    突出したものを検知することができる。

  • sampler aggregation es2.0の新機能
    例えば1ユーザにつき1ドキュメントだけ、とかできる。
    1ユーザが何百ドキュメントを持っている場合効率的。
    自分と同じものをよりたくさんlikeしている人は近い傾向を持っているとわかる。
    誰もが好きなバンドをlikeしているというのはあまり参考にならないが
    レアなバンドであれば大変好みが近いと言える(TF-IDFの応用)
    sampler aggregationを使えばより効率的に、すばやくレコメンデーションできる。

  • wikipediaの記事をグラフ化した場合、各記事同士がたくさんリンクしている。
    共通のコネクションが大事。
    たくさん調べればスーパーノード(共通してリンクしているノード、記事)がわかる
    でも、人名が人物とリンクしているという情報なんかは意味があまりない。

    カンファレンスで、どのwebサイトによく行きますか?と聞いたら
    githubとかstackoverflowと答えが出るでしょう。
    googleではなく、これがカンファレンス特有の答えです。

    人間が、世の中をどういう風に見ているのかと同じ考え方。
    データを期間で区切って調べる(週とか時間とかで)
    signficant term を調べたら何が得られるか?例えばハッシュタグで。
    その日で他の人に比べてたくさん使われているハッシュタグがわかる。
    トレンドがわかる。
    情報は力です。

    esを使えばよりたくさんの情報が得られる。

next stack

  • elasticsearch

    • task management api
    • reindex api
  • logstash (event hub的な)

    • clustering
    • persistent
  • kibana

    • custom app / plugins
  • Beats (fluentd agent的な)

    • packetbeat
    • filebeat
    • topbeat
  • commercial plugins

    • pdf reporting
    • orchestration / automation

Amazon SQSのテストでelasticMQを使おうとしてちょっとハマった話

最近はもっぱら AWS を使ったサービスの開発をしている。
あいかわらず、サーバサイド(Java)の開発+ちょっとインフラも。

さてさて、今回は Amazon SQS を使うことになった。
SQS周りの単体テストをしょうということで elasticMQ っていう子を使うことになりました。

adamw/elasticmq · GitHub

今回はそのelasticMQの使い方でちょっとハマっている話。

elasticMQはAmazonSQS互換のインターフェースを持っている子で起動の仕方は大きく2種類ある。
Readmeにも書いてあるけども

  • プロセスとして起動する方法
    java -jar elasticmq-server-0.8.8.jar

  • JUnitとかのテスト内で起動する方法

val server = SQSRestServerBuilder.start()
// ... use ...
server.stopAndWait()

ローカル環境で開発するときにはプロセスとして起動しながらサーブレット起動して動作確認したり。
JUnitでの単体テストのときはテスト内で起動したり。そんな感じで使ってる。

で、CI環境では(ちょっとテストがいけていないっていうのもあるけども)
プロセスが起動してあることが前提で動くAPIのRESTテストと
テスト内で起動して動作確認をする単体テスト両方が動く。

この時にテストの中でキューのメッセージを消しているはずなのに消せない!って問題が起きた。
というかそもそもキューがない!って言われる。

流れはこんな感じ。
maven testを流すと下の流れでテストが動く。

  1. RESTのテスト
    1. APIのテストを実施(この中でプロセスElasticMQにメッセージを発行)
  2. 単体テスト
    1. テスト内でElasticMQ起動
    2. ElasticMQに接続してキューを削除(しているつもりだった)
    3. テストで起動したElasticMQにメッセージを発行
    4. メッッセージの確認(APIテストのメッセージが残ってる!!)

ちゃんとした原因は、まだわかっていないんだけども

$ netstat -an | grep 9324

tcp46      0      0  *.9324                 *.*                    LISTEN     <---- プロセスで起動したElasticMQ
tcp4       0      0  127.0.0.1.9324         *.*                    LISTEN     <----テスト内で起動したElasticMQ

このように起動したプロセスが同じポート使って別ヤツもので動くっぽい。
ポートってぶつかってたらダメなやつだと思っていたけども
「tcp46」と「tcp4」だったら別ヤツでうごけるの?
それともアドレスが「*」と「127.0.0.1」 だから?<--多分こっち (ここわかってないのでインフラ先生に教えを乞おう)

キューへのアクセッサーはシングルトンなので接続状態とかテストをどうやって実行するかも関係してて

  1. RESTのテスト
    1. APIのテストを実施(この中でプロセスElasticMQにメッセージを発行)
      (ここで「*.9324」へのコネクションを確立している)
  2. 単体テスト
    1. テスト内でElasticMQ起動
    2. ElasticMQに接続してキューを削除(しているつもりだった)
      (ここは「127.0.0.1.9324」へ接続、消しているつもりになっていた)
    3. テストで起動したElasticMQにメッセージを発行
      (こっちは「*.9324」に接続している)
    4. メッセージの確認(APIテストのメッセージが残ってる!!)
      (こっちは「*.9324」に接続している)

ということで失敗してしまっていた様子。

今回の対処方法は2つ?

1つ目

  • プロセス起動側の設定ファイルを指定する(elasticMQのReadme 参照)
    bind-hostname = "127.0.0.1"
  • テスト内の起動時にすでにプロセス側が起動していたら(java.lang.RuntimeException: Binding failed.例外が発生したら)スルーする。

2つ目

  • テスト内の起動時にインターフェースを「"0.0.0.0"」で設定して、 すでにプロセス側が起動していたら(java.lang.RuntimeException: Binding failed.例外が発生したら)スルーする。
SQSRestServerBuilder.withInterface("0.0.0.0").start();

1つ目のやり方だと他の人にも影響がでてしまうので2つ目のやり方で試してみようと思う。

Amazon Linux で yum update したら Ansible が動かなくなった

今日Amazon Linux 上でAnsibleを実行したら

--

ImportError: No module named yum

--

とか言われて動かなくなった。

 

つい先日まで動いていたのに、なんでやねんとおもいつつ調べてみたら
どうやら Amazon Linux 2015.03 がリリースされていて色々と変わっていたらしい。
(何でこんなタイムリーなんだ…と思いつつ)

Amazon Linux AMI 2015.03 Release Notes

今回問題になったのが 「Python 2.7 by default」となったこと。
Ansible で yum update を実行しているのだけど
それでpythonのバージョンが上がっていた。

 

バージョンが上がっても普通に動いてくれればいいんだけど、
python2.6側が動かなくなっているみたいで
Ansibleの実行対象サーバ側で

--

> python
> import yum

--

とするだけでもエラーとなった。

 

この事象を回避するには、Ansibleの実行対象サーバ側で

sudo alternatives --set python /usr/bin/python2.7

としてあげれば動くようになった。

 

Ansible側で

--

ansible_python_interpreter="/usr/bin/python2.7"

--

とやっても動きました。


しかしどうも、なんだかなぁという感覚なので
今回は yum updateでアップデートしないようにした。

 

/etc/yum.conf の

---

releasever=latest 

---

---

releasever=2014.09

---

 

のようにしてあげれば、リポジトリ先を指定することができて
pythonが上がらないようにできる。

もうちょっと様子見てからどうするか考える。

 

イテレーションについて考える

最近うちの上司がイテレーションをなくしたいということを言っているので、
なくすことによってどんなメリットがあるのか、
そもそもなんでイテレーションが存在するのかについて考えてみることにする。

イテレーション

うちは2週間でイテレーションを区切っている。BtoBtoC。
最初に計画を立てて、物を作り、最終テストをしてリリースする。という流れ。

イテレーションとはつまり期限を決めることか?
違う、イテレーション=反復という意味らしい。

イテレーションがあることによるメリット

顧客と開発者、両方の目線で考えて見る。

顧客からの視点

  • ある程度、いつまでにできるかわかる
    これはどうだ?そもそも、今のうちのやり方がおかしいからこういう発想になるのではないか?

  • 計画、レビューのみ参加するってことができる
    がっつり入り込めない忙しい人には嬉しいのかもしれない。
    でもこれもちがう、ダメだと思う。

開発者の視点から

  • 開発リズムができる
    計画を全員で立てればなんとなく全体の状況が把握できる。終わったーっていう達成感とか。
    あとは、この日までにここまでやらなきゃいけないという気持ちにさせてくれる。

  • 進捗を管理できる
    もう完全に何のためだかわからなくなってきた。

イテレーションがないことによるメリット

顧客からの視点

  • できたものがすぐに提供できる
    イテレーションで区切ると最後のタイミングで一斉にリリースってなるけど、それがなくなる感じ。

開発者の視点から

  • 期限に間に合わせようと品質を犠牲にしなくなる
    やはりなんとか間に合わせようとしてしまうことはある。

  • 物を作る、以外の付加価値作業ができる ここまでにこれ終わらせなきゃ、ってならないと
    なんかこの作業いつもめんどくさいから自動化するかって発想になりそう。
    自分が作ったものの使われ方とか気になって、ログ解析とかしそう。
    いや、ちゃんと顧客にその価値を伝えてやらせて貰えばいいんだけど、

  • 進捗を管理しなくていい
    ちょっと言い過ぎかもしれないけど。
    でもさぼるやつでそう。俺みたいな。

現状を踏まえての結論

今のままではイテレーションをなくすことはできないんだと思う。
「相手にこの機能をここまでに出します」って約束しちゃってるから、
そうするとイテレーションなりなんなりで進捗の管理をせざるを得ない。

でも、イテレーションがある意味があまりない、かな。
「不完全」な状態でも一旦見せて、フィードバックを受けて成長させるということができていないから。
最初から特定の機能をどーんと作って、それで終わり。というものが多い。
ちょこっとはフィードバック受けているだろうけども、なんか違う気がする。
ただ2週間ごとにやることを決めているだけな感、それじゃそんなに意味なくない?

ぬあああああ、結論、「進捗管理」のためのイテレーションになっているのでなくすことはできない思います。

なくすためにはお客さん、さらにはその先の先まで思想の共有をして納得してもらって
もっと透明性のある情報共有を行なっていく必要がある。

とは言ってみたが

個人的になくすことは賛成。
進捗管理なんて、エンドユーザからしたら何の意味もない。
大型リリースとかならともかく、細かい改善やバグフィックスは許可なんて得ないでどんどん出していけばいい。 もっと意味のあることに時間を費やすべき。
自由にやらせた方がいいものができるんじゃない?(→これは妄想かもしれぬ) そのためにいろんな仕組みが必要になると思うけど、自分がこっちのほうがいいと思った以上それに向けて頑張る。

elasticsearch 勉強会 第6回

Aggregationあれこれ

  • Facetはdeprecated。2.X系でなくなるらしい
  • Group by color : Bucket
    検索結果のドキュメントを分類
  • Count(color) : Metric
    Bucket内のドキュメントのデータをもとに計算
    ドキュメント数、平均値や最大値など
  • shard毎にAggsして、最終的にノードがマージする
    検索と同じ仕組み、クエリフェーズで実行
  • post_filterはAggsの影響を受けない
  • filterr aggsはAggsのみに影響して、検索結果には影響しない
  • Bucket
    • terms Facetの代わり、結果は近似値
      shard毎で最初に足切りされている。shard_sizeを使うとチューニングできる
    • significant terms
      異常検知、レコメンドなどに利用?
    • keydクエリ
      結果にkeyをつけて名前がわかりすくできる
  • Metric
    • stats はmin/max/avg/sum
    • cardinality SQLのDistinct
      近似値(HyperLogLog++) 最大40,000まで指定可能
      precision_threshold あげるとメモリを消費する
    • persentiles パーセンタイル
      compressionでメモリ使用量を調整可能
    • top-hits ★ $expand ?! グルーピングされた検索結果(Filed Collapsing)に検索できる
      Bucket内のドキュメントを結果として出力
      メモリを食うらしい。
    • scripted metrics 1.4.0で導入予定

秒間3万の広告配信ログをElasticsearchでリアルタイム集計してきた戦いの記録

  • ディスプレイ広告配信DSP Smalgo
  • 広告主 -> DSP -> アドネットワーク/SSP -> ユーザ
  • impression / click / conversion それぞれでログを出しており
    FluentdでElasticsearchに入れる
  • mark 行動履歴もログに落とし込んでElasticsearchに入れる
  fluentd 10node -> ELB -> | Elasticsearch coordinate Node  (write)   2node r3.large
  kibana         -> ELB -> | Elasticsearch Data Node        (read)    2node r3.large
                           | Elasticsearch searchNode                28node
                           |     12shard 1replica r3.xlarge / 1GB SSD
  • kibanaはエグイクエリを発行するので使いすぎると負荷が上がるw
  • 柔軟だがインデックスとドキュメントの設計は大事
  • 1日1.5TB (primary & replica)
  • データドライブのEBSをSSDに変更して高速化
  • 検索処理のキャッシュ化(ElastiCache)
  • バージョンアップの話はうちでも使えそう
  • indexingのパフォーマンスアップ -> johtaniさんのブログ

Elasticsearch日本語スキーマレス環境構築と、ついでに多言語対応

  • dynamic templates & index templates を駆使する
  • dynamic templates
    • 最初にマッチしたtemplatesが使われる
  • index templates
    • nodeの再起動は必要なく、新規で作成したインデックスのみに適用される
    • _analyzer path langage
      -> 多言語対応の部分は後で見たい

elasticsearchソースコード読みはじめてみた

非常に勇気をもらえた。
おらでもソースを読めそうだ!?

  • クエリを受けて結果を返す部分から読むのがベター と言われたものたどりつくのも大変!
  • ノード起動から導入した時のお話

reroute APIを使用してシャードの配置を制御する (LT)

  • 複数シャード移動のはまりどころ
    自動再配置に注意!自動再配置を抑止するべし。
  • Bonsai is cool !!
  • shardの移動でRemoteTransportExceptionが頻発
    (shardが多すぎる?)

タグを振って配置することもできる(whereness?)

検索のダウンタイム0でバックアップからIndexをリストアする方法 (LT)

  • snapshot & resotre api
  • 無停止でバックアップできる!
  • リストアにはIndexをいったん削除 or closeする必要がある!無停止できない!
  • index alias & restore api rename_replacement field
  • リストア実行後にAliasの削除! → include_aliases : false