Chatwork Creator's Note

ビジネスチャット「Chatwork」のエンジニアとデザイナーのブログです。

ビジネスチャット「Chatwork」のエンジニアとデザイナーのブログです。

読者になる

Biryani プロジェクト(メッセージ検索機能のCloudSearchからElasticsearchへのリプレイス)について vol.1

こんにちわ、SRE部のcw-tomitaです。
今回は、7/17(金)に行われた全社合宿で、プロジェクトとしては惜しくもベストPJ賞を逃したものの、オーディエンス賞を受賞(全社跨いで、半期の間に実施された数々のPJの中で厳選された3つのPJだけが賞をもらえる)し、また、このプロジェクトをリードしたcw-kajiwaraが、このプロジェクトを通しての圧倒的なコスト削減の実績からCFO賞を個人受賞するという、上期の社内の賞レースを席巻した、メッセージ検索機能のリプレイス(通称:Biryani PJ) *1 に関して紹介したいと思います。

写真は、先週行われた全社のオンライン(役員・準備/進行担当の方を除く)合宿での、感動の受賞シーン。 f:id:cw-tomita:20200721152720p:plain

目次

tl;dr

  • 5年以上前に構築されたCloudSearchベースのメッセージ検索機能をからElasticsearchに引っ越したことで、ユーザ体験の向上、大幅なサーバコスト削減に繋がりました。

  • ChatworkのElasticsearchの使い方のユースケース紹介と、移行にあたって検討・調査した内容、実装/運用で工夫したポイントの共有。

    • これから、Elasticsearchの利用開始したり、他の検索クラスタからの移行を検討していく人の参考になったら、とても嬉しい!

移行前の構成

移行前のCloudSearch版の構成等に関しては、以下にまとまっているので、この記事では割愛します。こちらをご覧いただければと思います。

aws.amazon.com

この仕組み、そして、CloudSearchは大変によく出来ていて、5年以上、大きな事故なく、ほぼ運用レスで稼働してきました。凄い!!

移行を検討することになった背景

ただ、いくら良くできているとは、5年前と今とでは、Chatworkというサービスの規模 / 構成が大きく変わっていて、以下のような課題がでていました。

規模の変化

先のブログではメッセージ数は4億とありましたが、現在は15倍の60億以上のメッセージが存在(2020/6末時点)します。CloudSearchのクラスタでは、時系列でindexを分けるといったことは行われておらず、検索パーティション数が上限に近づく度に、都度、上限緩和申請を出しながら凌いできたのですが、

Amazon CloudSearch の制限の概要 - Amazon CloudSearch

検索インデックスは、最大 10 のパーティションに分割できます。この制限を引き上げる必要がある場合は、リクエストを送信できます。

いよいよ、1つのclusterでこれ以上パーティションを増やした場合に動作の保証をしかねるので、これ以上に緩和はできません、、というハードリミットを通達され、データ量の伸び具合から、そのパーティション数に到達するのに一年もかからないだろうという状況になりました。
また、AWSのinstanceのCPUやディスクの進化が続いてる中で、5年前のinstance typeを使い続けていることによるコスト効率の悪さも、データ量が増えるにつれて、どんどんと顕著に感じるようになってきていました。(PJ開始前は実際に試算できていたわけではないが、巷の最新の検索cluster構成の話などを聞いていると、自社のclusterは相当に効率が悪そうだった。)

構成の変化

CloudSearch版が実装された時は、Auroraにチャットメッセージデータを格納していたため、メッセージデータが登録されたことをトリガーに別途イベントを発火(詳細は先に紹介した事例リンクを参照してください)し、そこからCloudSearchにデータ反映を行うというフローになっていました。
一方で、CloudSearch検索が実装された2年後、2016年の年末にメッセージ基盤のリプレース(これに関しては以下の資料を参照してください)が行われ、これによってKafka上にメッセージ投稿イベントが記録されるようになりました。
ChatWorkの新メッセージングシステムを支える技術 - Speaker Deck

Worldwide Scalable and Resilient Messaging Services by CQRS and Event…

これによって、理論上は、Kafka上のメッセージベースで処理できるようになったのですが、当時は工数の関係から、元の仕組みをほぼそのまま残して、最小限のコード変更で元の仕組みを活用するという選択を行いました。
当時の状況を鑑みると妥当な選択ではありましたが、Kafka上にイベントして存在するものを、再度DynamoDBやSQSのイベントして登録するのは、コスト効率的にも良くないし、なくてもいい複雑さをシステムにもたらしているので、ここの余剰なフローを整理して、Kafka上のイベントを別のconsumerで処理する方式にしたいという思いもありました。

言葉だけだと伝わりずらいかと思うので、少し順番が前後してしまいますが、before / afterの構成図を以下に貼っておきます。

before (Kafka導入前からあったインターフェイスを利用するために、Kafkaから吸い出したイベントを、SQSに積み直している) f:id:cw-tomita:20200722182052p:plain

after (Kafka上に積まれたメッセージを元に、直接Elasticsearchに反映) f:id:cw-tomita:20200722182512p:plain

移行先の検討の開始

これらのような課題を元に、移行PJが始まりました。
このPJでの1番の肝は新しい検索クラスタに何のミドルウェアを選択するかでした。本来、こういうPJの進め方の王道としては、候補をいくつか出してpros/consを比較しつつ、必要に応じて機能テストや負荷テストをしていく、、という流れが一般的かと思いますが、このPJでは、まず第一候補としてElasticsearchに対象を絞って、POC(= Proof of Concecpt)を行うという方法を選択をしました。
理由としては以下の2つが挙げられます。

  • CloudSearchは、コスト効率的な問題は感じていたが、ほぼ運用レスで安定して動き続けてくれていて、その面ではとても助かっていた。そして、現状のシステムの運用体制を鑑みるに、新たに管理すべきクラスタが増えるというのは、他のメリット(主にサーバコスト部分)を犠牲にしても避けたい状況。このため、移行先もmanagedなサービスで提供されているミドルウェアを選択したい。そして、今回想定している規模を安定して捌けそうな実績あるmanagedな検索クラスタはElasticsearchベースのものしか見つけられなかった。
  • 事前調査を行なっている中で、Elasticsearchで構築するclusterで、向こう数年に渡って十分にChatworkの負荷を捌けそう、、と思える発表や事例を見つけた。

もし、何らかの理由で、Elasticsearchが使えない!ってなったら、他のミドルウェアを検討 or CloudSearchのindexを時系列 (message-2020, message-2019....) に組み直して、複数clusterで処理するようにしてハードリミットを避けつつ、アプリケーションで結果をmergeする形かな、、というような話はしていましたが、幸い、これらの方式を深く検討することはありませんでした。

Elasticsearchの事前調査

先の段落で、事前調査云々の記述をしましたが、以下、参考になったリンクと概要を2つほど紹介します。(これらは2019年の前半に調べたものなので、今だと、もっといいものがいっぱいあるかもしれません。)
これらの事例や発表を見ていて、Chatworkのメッセージ検索をElasticsearchで良くすることは可能そうだなという思いを皆んなで高めて、PJが動き始めました。(そして、この記事も、これから何らかの形でElasticsearchやってく人の思いを高めるきっかけになったら、うれしんでぃ!)

Powering Large-scale, Full-text Search for the UK Government Web Archives using Amazon Elasticsearch Service (2017年のRe:Invent の発表)

資料

ABD338_MirrorWeb - Powering Large-scale, Full-text Search for the UK …

動画

www.youtube.com

参考になったポイント

  • Elasticsearch Serviceユーザがあれこれと試行錯誤しながら、巨大データセットをデータマイグレーションして、検索システムを構築した話。サービスの特性は違えど、データ規模として近しいものがあり、しかも2年前(当時から見て)の事例で、マシンもミドルウエアも当時より良くなっているはずだし、2年前でこれがいけたんだったら、我々もいけそうだな、、と強く思わせてくれた発表。
  • サービスやデータの特性はだいぶ違いそうだけど、初期データマイグレーションがあって、その後に通常検索システムとして提供という所もユースケースも似ていた。
  • 初期データマイグレーションで、cluster sizeをがちゃがちゃやる所はとても参考になったし、実際に自分たちがやったSparkを使ったデータマイグレーションでも似たようなアプローチを取った(詳細は後述予定)。
  • 1 shardあたり200GB程度を超えていそうで、一般的に推奨される使い方とは違いそうだけど、やはり、そういったチューニングありなんだなという学び。Chatworkのメッセージ検索も一般的な検索とはちょっと違う特性があるので、その辺りをどう吸収していくことになるのかな、、?というイメージングの始まり。

Get the Most out of Your Amazon Elasticsearch Service Domain from Re:Invent (2018年のRe:Invent の発表)

資料

Get the Most out of Your Amazon Elasticsearch Service Domain (ANT334-…

動画

www.youtube.com

参考になったポイント

  • Elasticsearch cluster運用にあたって、ベースとなる考え方、抑えるべきチューニングポイントを簡潔にまとめてくれていて、ここで紹介されてる内容をベースに、じゃあ、Chatworkのユースケースではどうすべきか、、?と考えることができた。
  • 利用すべきinstance typeについて
    • ある程度のデータボリュームになるのであれば、i3がおすすめ
  • shard数設定の基本となる考え方
  • refresh_intervalの話
    • 書き込みの仕組みと合わせて説明があって良かった。
    • ChatworkのユースケースではWriteヘビーなので超重要。

vol.1 の締め

移行を検討するに至った経緯、なぜElasticsearchに絞って取り組み始めたかの紹介だけで、結構なボリュームになってしまったので、、この記事はここで一旦終了として、続きはvol.2に書きたいと思います!

ということで、キックオフランチで食べた大阪の中津駅近くのダイヤモンドビリヤニのビリヤニの写真でvol.1の記事を締めさせていただきます。

お約束にはなりますが、Chatwork SRE部では、様々なミドルウェアと触れ合いたいエンジニア、一緒にビリヤニ談義をしたいエンジニアを絶賛大募集中です!

www.wantedly.com

SRE部だけでなく、他にも色んなポジションありますので、美味しいBiryaniを食べたい方は是非!!



2020/07/22 追記
vol.2 出ました!!
creators-note.chatwork.com

2020/07/22 追記 ここまで


www.wantedly.com

tabelog.com

f:id:cw-tomita:20200706152648j:plain

f:id:cw-tomita:20200706152721j:plain

*1:PJのキックオフ前のランチにBiryaniを食べ、あまりの美味しさに感動し、以後、いくつものBiryani専門店を食べ歩くほどのBiryaniフリークとなったcw-adachiによって、Biryani PJと名付けられました。