kickflow Tech Blog

株式会社kickflowの開発チームによるブログ

Elasticsearchのインデックス切り替えを無停止で行えるようにしました

こんにちは。エンジニアの森本です。

テキストでの全文検索はどのような仕組みを利用されていますか? kickflowでは、全文検索エンジンとしてElasticsearchを使っています。これまでは、1つのインデックスで検索を行っていたため、マッピングの変更時にダウンタウンが発生してしまう問題がありました。そのため、マッピング変更時には計画メンテナンスを設けてインデックスの再作成を行っていました。しかし、データ量が増え続けていること、これからもインデックスのマッピング変更が発生することを考えてメンテナンス期間を設けずにインデックスの再作成が行える仕組みを導入しました。

どのような仕組みを導入したのかをご紹介したいと思います。

やったこと

結論としては、エイリアスの仕組みを使って無停止切り替えを実現しました。そのため、読み取り処理はエイリアスを指定する必要があります。

以下のページを参考にさせていただきました。

techlife.cookpad.com

www.elastic.co

ざっくりと無停止切り替えの作業の流れを説明します。

インデックスの追加

まずは、新しいマッピング設定のインデックスを追加します。

このとき、切り替え前後のインデックスが共存できるようにそれぞれにドキュメント作成用のクラスを用意しておきます。 ちなみに、インデックスを作成前にドキュメントを作成すると自動でマッピングを定義してインデックスが作られてしまい期待したマッピング定義にならない可能性があります。kickflowでは、新旧のインデックスが存在している移行期間だけはインデックスが定義されているかを確認することで自動でインデックスが作成されないように制御するようにしました。

インデックスへの同時書き込み

Elasticsearhへのリクエストは主に、更新と読み取りの2種類に分かれます。

更新はインデックス単位、読み取りはエイリアス単位で行うようにそれぞれ設定します。読み取りはエイリアスを指定しておくことで、新たに作成したインデックスのデータ同期が完了していなくても併存させることが可能です。更新処理は、現行のインデックスと上記で作成したインデックスそれぞれに対してドキュメント作成処理を行うようにしておきます。

エイリアスの向き先変更

作成したインデックスでデータが揃ったらエイリアスの向き先を変更します。この操作はダウンタイムなく行うことが可能です。

コード例は以下の通りです。エイリアスは何も参照しない状態にもできるので、設定が空にならないように注意が必要です。

# 切り替え後のインデックス名を指定して add
# new_index_name は切り替え後のインデックス名
actions << { add: { index: new_index_name, alias: ALIAS_NAME } }
# 切り替え前のインデックス名を指定して remove
# old_index_name は切り替え前のインデックス名
actions << { remove: { index: old_index_name, alias: ALIAS_NAME } }

client.indices.update_aliases(body: { actions: })

旧インデックスの削除

ここまでで、本番環境で不具合が発生しなければ参照されていないインデックスを削除します。

この手法のメリットはマッピングが大きく変わらない限り、切り替え前後の状態を保持しつつ何かあれば素早く戻せることです。インデックスを一つで運用していると不都合があったときに元に戻すために時間を要します。

デメリットとしては、一時的にデータ容量が2倍、インデックスへのドキュメント作成処理が2倍になるのでリソースを消費します。リソースに余裕があることを確認した上で実行するようにしましょう。

We are hiring!

kickflow(キックフロー)は、運用・メンテナンスの課題を解決する「圧倒的に使いやすい」クラウドワークフローです。

kickflow.com

サービスを開発・運用する仲間を募集しています。株式会社kickflowはソフトウェアエンジニアリングの力で社会の課題をどんどん解決していく会社です。こうした仕事に楽しさとやりがいを感じるという方は、カジュアル面談、ご応募お待ちしています!

careers.kickflow.co.jp