Amazon Web Services ブログ

ゲームにおけるリーダーボードを Amazon MemoryDB for Redis で再考する

この記事は、”Rethinking Game Leaderboards with Amazon MemoryDB for Redis” を翻訳したものです。

マルチプレイヤーゲームの人気が高まるにつれ、リーダーボードは開発者がユーザー間の競争を活発にするために不可欠なツールになりつつあります。一方で、リーダーボードの基本的な構成は変わっておらず、順位を管理するという同じ目標を達成するにはいくつかの方法があるため、リーダーボードのバックエンドテクノロジーは様々な場面で議論されてきました。この投稿では、Amazon MemoryDB for Redis をリーダーボードバックエンドを支える優れた選択肢として紹介します。このブログでは耐久性を得られつつ、マイクロサービスアーキテクチャへと繋げ、複雑なメインサービスのもつれをどのように解消するかについて説明します。

背景

ゲーム開発をしていく中で、リーダーボードデータの耐久性を高めるという課題がでてきます。この問題を解決するための一般的なアプローチは、Amazon ElastiCache for Redis と永続的なデータベースレイヤーを組み合わせて使用することです。

1つの方法は、リーダーボードスコアの原子性を担保することです。よくある方法として開発者は Redis API 呼び出しを永続的なデータベーストランザクションでラップすることがあります。たとえば、Amazon Aurora をプライマリデータベースとして使用し、MySQL トランザクションを使用して Redis の書き込みをラップするとします。この場合、Redis に書き込む全ての API 呼び出しはトランザクションでラップされている必要があり、その作業に時間や労力がかかります。

もう1つの方法は、結果整合性のもとでの運用です。Amazon DynamoDB を使用すると、開発者はDynamoDB Stream を使用し、リーダーボードスコアの変化をキャプチャし、最終的に Redis でデータを更新することができます。非同期で Redis のスコアが更新されるため、ゲームクライアントはスコアの更新に合わせる必要がありますが、ゲームは非同期な更新に寛容であることが多いためこの方法もよく見受けられます。

3つ目の方法は、cron ジョブを一定の頻度で実行させることです。例えば、開発者は Amazon EventBridge でスケジュールされたジョブを簡単に設定し、永続レイヤーをスキャンして Redis を更新でき、逆に Redis をスキャンして永続レイヤーを更新することも可能です。2つ目の方法と3つ目の方法はいずれも時間の経過とともにデータを同期しますが、これにより、クライアントが Redis もしくは永続レイヤーのどちらかから一貫してスコアを読み取っていることを確認する内部サービスのルールが不可欠になります。1つ目の方法では、データは2つのデータストレージで同期されますが、場合によっては読み込み用のトランザクションも必要になるかもしれません。

永続レイヤーは、ユーザー名、スキル、アバターなどの他のユーザーデータを保持するケースが多いです。これにより、同じ場所でユーザースコアを保持するという考え方も生まれます。この考え方は一般的であり、小規模なゲームではうまく動作するかもしれません。しかし何百万人ものプレイヤーがいるスケーラブルなバックエンドにはデータベースの分解が必要となるでしょう。

Redis用Amazon MemoryDB のご紹介

Amazon MemoryDB for Redis は、Redis と互換性のあるフルマネージド型のインメモリデータベースサービスで、耐久性が高いのが特徴です。MemoryDB は、耐久性を維持するために Multi-AZ トランザクションログを使用するインメモリストレージにデータを格納します。また、このサービスでは、Redis の超高速なパフォーマンスを維持・継承しながら、災害から復旧する堅牢な機能も導入されています。したがって、このユニークな特徴はゲームのリーダーボードに適合し、これまでのようにリーダーボードを管理する際に複数のデータストレージにわたって整合性を管理する必要がありません。

MemoryDB は高速で信頼性が高いだけでなく、スケーラブルでもあります。ゲーム開発者は、ノードを追加または削除して MemoryDB クラスターを水平方向にスケーリングすることも、ノードタイプを選択して垂直方向にスケーリングすることもできます。これらのスケーリング操作は、呼び出し元から完全に透過的です。つまり、リーダーボードを追加しても、ライブゲームのメンテナンスは必要ありません。

Amazon MemoryDB を使う

Amazon MemoryDB for Redis では、すべてのリーダーボードデータを個別に保存できるため、同じスコアデータをプライマリデータベースに保存する必要はありません。よって、例えばプライマリーデータベースに Amazon Aurora を使用した場合に新しいリーダーボードの新しいスコアデータを追加するとしても、そこに新たなトランザクションが必要にはなりません。プレーヤー ID などで管理されたリーダーボードのオペレーションは、他のプレイヤーステータスのオペレーションから完全に切り離されることはないので、2つの場所でデータをモデリングし2つのデータソースを同期する従来のやり方よりも、新しい機能をゲームに追加する際に管理が簡単です。また、ゲームでリーダーボードに関連したメタデータが必要な場合は、MemoryDB を使用してメタデータを保存する事もできます。

マイクロサービスとしてのリーダーボード

ゲームには、シーズンリーダーボード、ウィークリーリーダーボード、ギルドリーダーボード、ライフタイムリーダーボードなど、さまざまな種類のリーダーボードがあります。それらのほとんどは異なるスコアを保存しますが、基本的に中の作りは非常に似ています。実際、個々のリーダーボードの固有の属性をすべて外に取り出し、1つの汎用サービスを作成して、あらゆる種類のリーダーボードを管理する事も可能です。Amazon ECS または AWS Lambda を MemoryDB と組み合わせることで、スケーラブルなリーダーボードサービスを作成できます。これで、メインのゲームサーバーとは別にスケーリングできる完全なリーダーボードマイクロサービスが完成します。さらに、名前空間を追加したり接頭辞を付けたりすることで、まったく同じ組み合わせで複数のゲームをサポートする共通基盤として活用する事もできます。こうすることで、ゲームクライアントはサーバーを通して MemoryDB という一貫した場所からすべてのスコアを取得することになります。以前別のブログで紹介した MemoryDB を使用したマイクロサービスのサンプルアプリケーション及びベストプラクティスと実装の詳細な説明がありますので、是非このブログの最後にリンクからご覧ください。

まとめ

特定の要件に合わせた複数のデータベースの管理は簡単な作業ではありませんが、Amazon MemoryDB for Redis などゲームの特定の機能にとても合ったサービスが AWS にはあります。ゲーム開発者は、アーキテクチャ上の利点を活用することによって、ゲームをより面白くする機能開発の作業に集中することができるでしょう。

リンク

Redis を使ったリーダーボードの作り方

MemoryDB を使ったマイクロサービスのサンプルコード

原文はこちらです。
Game DevRel 石井 宇大(@takahiroishii_)