Amazon Web Services ブログ
Tinder における大規模な回復性構築のための Amazon ElastiCache の利用
この記事は、Tinder 社の William Youngs 氏 (ソフトウェアエンジニア) 、Daniel Alkalai 氏 (シニアソフトウェアエンジニア) 、Jun-young Kwak 氏 (シニアエンジニアリングマネージャー) らの寄稿によるものです。Tinder は、2012 年に大学のキャンパスで生み出され、世界で一番利用されているマッチングアプリに成長しました。現在までに、このアプリは 3 億 4,000万件以上ダウンロードされており、190 の国々において 40 以上の言語で利用されています。2019 年の第3四半期時点において、Tinder には 570 万人の登録者がおり、ゲーム以外のアプリの中では世界で最も成長しているものとなっています。
Tinder の業務は、毎日 20 億件におよぶメンバーからのアクションに対応しながら 300 億件のマッチングをホスティングするために、低レイテンシーを Redis ベースのキャッシングにより実現しています。ここで行われるデータオペレーションの主体は読み込みです。次に示す図が、当社のバックエンドマイクロサービスにより大規模な回復性を実現するための、基本的なデータフローアーキテクチャを説明しています。
このキャッシュアサイドアプローチでは、データを要求されたマイクロサービスは、信頼できる情報源である永続的データベースストア (主として Amazon DynamoDB ですが、PostgreSQL、MongoDB、Cassandra も使用する場合もあります) を参照する前に、まず、Redis によるキャッシュへのクエリを行います。このサービスでキャッシュミスが発生した場合は、Redis に対して真実の情報源から値の埋め戻しが行われます。
当社では、Amazon ElastiCache for Redis を導入する以前には、Amazon EC2 インスタンスにアプリケーションベースのクライアントを置き、そこでホスティングされた Redis を使用していました。このシャーディングは、静的パーティショニングに基づき、キーをハッシュすることで実現しました。上記の図 (図 2) では、EC2 において Redis をシャードするための構成を示しています。
特にいえるのは、このアプリケーションクライアントでは、(シャードやレプリカの数、インスタンスサイズなどが) 固定的な構成の Redis トポロジーに頼っていたということです。アプリケーションは、構成が固定されたスキーマのトップにあるキャッシュデータをアクセスすることになります。このソリューションが使用する固定的な構成は、シャードの追加やリバランスの際には大きな問題となりました。自社で実装したこのシャーディングソリューションは、当初は十分に機能していたのも確かです。とはいうものの、Tinder の利用者とトラフィックのリクエストが拡大すると同時に、Redis インスタンスの数も大きくなり続けました。これによって、オーバーヘッドが増大し、その維持も大変な仕事になったのです。
動機
1 つめの動機は、シャード化された Redis クラスターの維持作業の負荷が問題化していったことです。この Redis クラスターの維持ために、かなりな量の開発時間を浪費しなければなりませんでした。このオーバーヘッドにより、当社のエンジニアたちが本来集中するべきであった技術的取り組みが、遅延する結果となったのです。たとえば、クラスターのリバランスには大変な労力を要します。リバランスのためだけに、クラスター全体を複製する必要があるからです。
2 つめに挙げられるのは、当社での実装が抱えていた非効率性が、基盤レベルでのオーバープロビジョニングとコスト増大を招いたことです。このシャーディングアルゴリズムは効率が良くなく、技術者の介入を必要とするような負荷の思いシャードが、システム上の問題となっていきました。加えて、キャッシュデータを暗号化しようとしたときは、その暗号化処理は自ら当社で実装しなければなりませんでした。
最後に、そして最も重要な理由として挙げられるのは、手動で編成していたフェイルオーバーは、アプリ全体の停止を引き起こしていた点です。中核的なバックエンドサービスの 1 つであるキャッシュノードのフェイルオーバーにより、接続済みのサービスがノードへの接続を失うという事態が起きたのです。アプリケーションが必要とする Redis インスタンスへの接続を回復するために再起動するまでの間に、しばしばバックエンドサービスの品質が完全に失われました。そして何よりもこのことが、当社が移行を決定する最大の動機となったわけです。ElastiCache へ移行する以前では、Redis キャッシュノードのフェイルオーバーは、Tinder アプリが停止することの唯一最大の原因となっていました。キャッシュ用のインフラストラクチャを改善するためには、より回復力とスケーラビリティがあるソリューションが求められたのです。
調査
かなり当初から、キャッシュクラスターの管理タスクについては、可能な限り開発者たちが直接携わらなくてよいものに変えたいと考えていました。初期段階では、Amazon DynamoDB Accelerator (DAX) を当社のサービスに使うことが検討されました。しかし最終的には、いくつかの理由により、ElastiCache for Redis の導入が決定されました。
その理由の 1 つめは、既にアプリケーションが Redis ベースのキャッシングを行っていたことです。この既存のキャッシュアクセスパターンは、DAX ではなく ElastiCache for Redis への置き換えに馴染みが良いものでした。たとえば、Redis ノードの一部は複数の信頼できる情報源からのデータを保存していましたが、この用途向けに DAX を定義するための簡単な方法は見つかりそうにありませんでした。
2 つめの理由としては、これら両方のテクノロジーに対して行ったレイテンシーのベンチマークテストの結果が挙げられます。ここから、ElastiCache の方がより効率的でコスト効果も高いソリューションだという結論が得られました。Redis を基盤キャッシュタイプとして維持することにより、当社自身でホスティングしていたキャッシュノードを、設定エンドポイントを修正する程度のシンプルな作業で、マネージド型サービスと差し替えられるようになりました。
Redis エンジンをサポートしているマネージド型サービスの導入を決定した後は、すぐに、ElastiCache の選択が正解だ認識できました。ElastiCache では、当社のバックエンドが要求する 2 つの重要な要素である、スケーラビリティと安定性を満たすことができます。ElastiCache により、クラスターの安定性が見込めるというのは、非常に大きな魅力でした。移行以前は、不完全なノードやシャードのバランスにおける不適切さが、バックエンドサービスの能力に、悪影響を与えていたのです。クラスターノードが利用できる ElastiCache for Redis により、非常に大規模な水平的スケーリングが可能になります。
独自でホスティングしていた Redis インフラストラクチャを運用していた時代は、シャードの追加とスロットのリバランスを行うときは、新たに完全なクラスターを作成し切り替える必要がありました。現在では、AWS マネジメントコンソールでスケーリングイベントを起動すると、ElastiCache が追加したノードすべてでのデータ複製と、シャードのリバランスを自動的に行ってくれます。また、メンテナンスイベントを計画しておくと、その間に最小限のダウンタイムで、AWS が (ソフトウェアのパッチ修正やハードウェア置き換えなど) ノードのメンテナンスを行ってくれます。
加えて、すぐに使用できる暗号化機能が、ElastiCache のサポートとしてあらかじめ容易されているのも歓迎できるところでしょう。
理由として最後に挙げられるのは、AWS が提供する他のデジタル機能について、当社には、あらかじめ馴染みがあったことです。つまり、クラスターの状態は Amazon CloudWatch で簡単に監視できるということを、すでに理解していたのです。
移行戦略
次の図 (図 3) に、当社がとった移行戦略を示します。
始めに、新たにプロビジョニングする ElastiCache クラスターに接続するため、新しいアプリケーションクライアントを作成しました。旧来の独自ホスティングによるソリューションは、クラスタートポロジーの静的なマッピングに依存していました。一方、ElastiCache ベースの新しいソリューションでは、プライマリのクラスターエンドポイントが必要なだけです。この新しい設定スキーマにより、設定ファイルは大幅に簡素化され、システム全体を通じてのメンテナンス量も削減されます。
次に、旧来の独自ホスティングソリューションで実稼働中のキャッシュクラスターを、ElastiCache に移行します。これは、ElastiCache インスタンスが十分にウォームアップ (ステップ 2) されるまで、両方のクラスターにデータ書き込みをフォーキングすることで行います。「書き込みのフォーク」では、旧来の保存先と新しい ElastiCache クラスターの両方にデータが書き込まれることになります。ここで、ほとんどのキャッシュには各エントリーに TTL が関連つけられていますから、基本的にこのキャッシュ移行作業では埋め合わせ処理 (ステップ 3) は必要ありません。TTL の期間中に、新旧両方のキャッシュに対し、書き込みをフォーキングするだけです。ダウンストリームの信頼できる情報源であるデータストアが、キャッシュが埋められていく期間もすべてのリクエストに対応できるよう、確実にプロビジョニングされているのであれば、書き込みのフォーキングが、必ずしも、キャッシュインスタンスをウォームアップする必要はありません。Tinder では、基本的に信頼できる情報源であるデータストアをスケールダウンしたので、キャッシュ移行のかなり大きな部分で、書き込みのフォーキングによるキャッシュウォームアップが必要となりました。その上で、移行されるキャッシュでの TTL が大きい場合には、プロセス促進のために埋め合わせ処理を実行することもあります。
最後の段階で、切り替えをスムーズに行い新しいクラスターから読み出しを開始するために、メトリクスのログ記録により新しいクラスターのデータを検証しました。これにより、新規キャッシュのデータが旧来のノードと一致しているかを確認します。新旧両方のキャッシュ間での一致度合いが、許容できるしきい値に到達した時点で、新しいキャッシュへの完全な切り替え (ステップ 4) をゆっくりと行いました。切り替えが完了した時点で、新しいクラスターで付随的に行われた過剰プロビジョニングをスケールバックしました。
まとめ
クラスターの切り替えが進捗するにつれ、ノードの信頼性に関する問題の発生率が低下し、アプリの安定性にも著しく改善が見られました。現在では、AWS マネジメントコンソールでいくつかボタンをクリックするだけで、クラスターのスケーリング、新しいシャードの作成、そしてノードの追加が行えます。今回の Redis の移行により、当社の運用エンジニアに対し時間とリソースが大いに解放されました。同時に、モニタリングと自動化についても、劇的な改善が実現できました。その後、アプリケーションの Redis クライアントを、スムースなフェイルオーバーによる自動復旧が行えるよう最適化しました。詳細については、Medium の「Taming ElastiCache with Auto-discovery at Scale」をご参照ください。
今回行った、ElastiCache への機能的で安定した移行は、スケーラビリティと安定性について、即時的かつ劇的な改善をもたらしました。Tinder でのスタックに ElastiCache を導入するという今回の決断については、この上ない満足を感じています。
免責事項
この記事の内容および意見は第三者の作者によるものであり、AWS はこの記事の内容または正確性について責任を負いません。
著者について
Will Youngs 氏は Tinder 社の認証チームにおいて、ソフトウェアエンジニアを務めています。Youngs 氏は、ユーザーデータやユーザー認証を管理すスマイクロサービスの、構築と保守を担当しています。また、同社が行った Amazon ElastiCache への移行作業にも広く関わっています。
Daniel Alkalai 氏は Tinder 社の認証チームの、シニアソフトウェアエンジニアです。彼は、認証プラットフォームチームのリーダーとして、プロファイルデータ管理を担当しています。Tinder 社の主要なバックエンドサービスとインフラストラクチャをスケーリングする際に、そのパフォーマンスの維持を支援しています。
Jun-young Kwak 氏は、Tinder 社の認証チームのシニアエンジニアリングマネージャーです。 彼は、Tinder のアカウントを、そのメンバー同士が知り合うための究極の基盤として作り上げるための、技術的な業務を指揮しています。