この記事は Origami Advent Calendar 14日目の記事になります。
Origamiのアプリではお店を現在地から近い順に表示させたり、商品をスクロールで読み込ませたり、商品をキーワードで検索したりといった部分にはElasticsearchが使われています。
お店 | 商品 |
---|---|
少し前ではありますが、今年、OrigamiではElasticsearchのバージョンを1.5から2.3にアップグレードしました。その際の目的や苦労話、やったことについて書きたいと思います。
目的とゴール
まずは当時、商品検索が貧弱だという問い合わせが相次いでいたので、ちゃんとしようぜということになりました。(この時点では上記のお店の近い順表示は無かったです)
そして目的とゴールを掲げました。
<目的>
- 安心
- 検索機能の改善
- 検索精度の向上
<ゴール>
- Elasticsearchのクラスターとノードの監視
- クラスターが落ちた時の対応
- マッピング更新、辞書更新、インデックス再構築のフローをつくる
- 検索機能の改善指標を作り可視化できるようにする
- インデックスにカスタムアナライザをセットする
当初、1.5から2.3にバージョンアップすることは目的ではなく、ゴールまでの過程で2.3にするとインデックス再構築が楽になるとか、スループット上がるとか、marvel2.X(無償)が使えるという噂聞いたりだとかあって、バージョンアップしようということになりました。
苦労話
当初、構築済みの新ESサーバー(ver2.3)を用意し、旧ESサーバー(ver1.5)で取得したスナップショットを新ESサーバーでリストアし、各マイクロサービスのESサーバーの接続先を切り替えるという手順を考えていました。
しかしver1.5のスナップショットはver2.3でデータをリストアできないことが判明。ver1.X系のスナップショットを2.3でリストアするためには、ver1.5をver1.7に上げる必要がありました。
またスナップショットリポジトリの準備を全ノードに行う必要があるなど、作業が複雑になることがわかりました。
そこでRDB(リレーショナルデータベース)に商品のマスターデータがあるので、RDBからElasticsearchにデータをコピーするスクリプトを作成して、それの実行完了後、旧ESサーバーから新ESサーバーに接続先を切り替える方法にシフトしました。(※最初からこの方法思いついていれば苦労しなかった。)
その都度全てのデータをコピーすると時間を要するため、今後の運用のため、実行スクリプトは引数にタイムスタンプを指定することで、その時間以降のデータをコピーできるようにしました。RDBに保存されている商品データの更新時間(updated)以降のもののみコピーの対象とするようにしています。
スクリプトの例)
$ NODE_ENV=development coffee add_product_to_es.coffee 1481959661
やったこと
- 新ESサーバー(ver2.3)を準備する
- ショップ管理画面を停止、メンテナンス画面の表示(切り替えの間、商品更新されないよう)
- RDBからElasticsearchにデータをコピーするスクリプトを実行
- 各マイクロサービスの接続先を旧ESから新ESに切り替え
- ショップ管理画面を起動、メンテナンス画面の解除
移行中、ショップ管理画面は一時的に停止しました。スクリプトの実行によってESに対してRDBの商品データの商品登録(CREATE)と商品更新(UPDATE)は同期できるのですが、ESに既にコピーされてしまったデータに対してRDBの商品削除(DELETE)は同期できないためです。
所感
RDBに保存している商品のマスターデータがあると、Elasticsearchのような検索専用のサーバーを移行する作業はシンプルかつ効率化できることを実感しました。
来年にはElasticsearchをver5.Xに上げたいと思っています。Go製のElasticsearchクライアントにはelastigoを利用しているのですが、Elasticsearch5.0にはまだ対応できていないため、クライアント部分の入れ替えが必要となりそうでこの部分が来年の苦労になりそうな予感がしております。