📖

re:Invent 2024: Dream11がAWSで2億ユーザーに対応する技術

2024/01/01に公開

はじめに

海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!

📖 AWS re:Invent 2024 - Scaling technology for millions of cricket fans on AWS (MAE309)

この動画では、インドの大手Fantasy SportsプラットフォームであるDream11が、2億2000万人以上のユーザーを抱える大規模システムをAWSで運用する方法について解説しています。特に、Cricket試合開始30分前に1分あたり2億7000万リクエストまで急増するトラフィックへの対応や、2000万チームを数秒ごとにランク付けするリアルタイムLeaderboardの実現方法など、具体的な技術的課題とその解決策を詳しく説明しています。また、Scalerシステムによる事前トラフィック予測や、RAY serveを活用したDarwinによるパーソナライゼーション、Circuit Breakerを用いた障害対策など、大規模システムならではの独自の工夫も紹介されています。
https://www.youtube.com/watch?v=SOgX572YinQ
※ 動画から自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますので、正確な情報は動画本編をご覧ください。
※ 画像をクリックすると、動画中の該当シーンに遷移します。

re:Invent 2024関連の書き起こし記事については、こちらのSpreadsheet に情報をまとめています。合わせてご確認ください!

本編

Dream11とCricketの規模:インドのデジタル革命

Thumbnail 0

本日はご参加いただき、誠にありがとうございます。他にも魅力的な選択肢がある中、私たちのセッションにお時間を割いていただき、大変光栄に存じます。本日は、インド人にとって非常に情熱的なスポーツであるCricketの体験を、Dream11がAWSを活用してどのように向上させているかについてお話しさせていただきます。こんにちは。私はSatinder Singhと申します。インドのAWSでSolution Architectureチームを率いています。こんにちは。私はSrijan Guptaです。Dream11でVP of Engineeringを務めています。皆様、こんにちは。私はRachita Choudharyです。同じくDream11でVP of Engineeringを務めています。

Thumbnail 60

Thumbnail 70

Thumbnail 90

これからスケールについてお話しする前に、私たちが直面しているスケールに影響を与えている要因について理解することが重要だと思います。 まず1つ目は、インドの人口構成についてです。私たちは比較的若い国で、人口の約65%が35歳以下です。 2つ目の要因はインターネットの普及率です。私たちは13億人という大きな人口を抱えていますが、そのうち9億人がインターネットにアクセスできる環境にあります。 そして3つ目の要因はデータ通信コストです。インドはデータの手頃な価格という点で世界をリードしています。最近開催されたインド会議で首相が述べたように、1GBあたり12セントという価格です。このように、若い人口が多く、安価なデータにアクセスできる大規模な人口が、これから私たちが話すような環境を生み出しているのです。

Thumbnail 110

そこにCricketが加わります。インドは発展を遂げてきましたが、Cricketは今でも第二の宗教のような存在です。Cricketも大きく進化してきました。初期のCricketでは、試合は5日間かけて行われていました。最も長い試合は9日間続き、結果は引き分けでした。そこから現在では、T20という2チーム間で20オーバーを行う形式となり、通常3〜4時間で終了します。そして先ほど申し上げたように、これは非常に人気があり、このグラフが示すように、前回のWorld Cupでは5億人が視聴していました。

Thumbnail 200

私は意図的にこのスライドを選びました。これは特定の試合だけでなく、ほぼすべてのT20の試合で起こることです。このスライドを選んだ理由は、これがまさにここで起きたからです。これはWorld Cupの試合でした。前回のWorld Cupはアメリカとカリブ海地域で開催されました。皆様のいる場所に近いですね。さらに重要なのは、彼らがそのWorld Cupで優勝したことです。そのため、この5億人という数字は私たちにとって非常に重要なのです。 つまり、ファンにとってCricketは第二の宗教のようなものであり、より良い関わり方を求めているのです。これがFantasy Sportsの発展につながっています。オンラインゲーマーは4億9000万人おり、その大部分がFantasy Sportsに関わっています。そしてそのプラットフォームの1つがDream11です。

Dream11のスケールと技術的課題

Thumbnail 220

Thumbnail 250

Thumbnail 270

ありがとうございます、Satinder。最近のCricket World Cupをご覧になった方は、ユニフォームで私たちを認識されたかもしれません。今回のWorld Cupは、長年の悲願を達成できた特別な大会でした。こちらは私たちのチーム、インドのユニフォーム、女子チームと男子チーム、そしてTimes Squareに掲示された私たちのユニフォームの素晴らしい写真です。 私たちは誰なのか?私たちは世界最大のFantasy Sportsプラットフォームです。どれくらい大きいのか? ユーザー数はどれくらいだと思いますか?Satinderが先ほど5億人のCricketファンがいると言及しましたが、そのうちDream11のユーザーは何人だと思いますか?1億人?1億5000万人?実は、2億2000万人以上のユーザーがいるのです。

Thumbnail 280

Thumbnail 290

Thumbnail 300

昨年だけでどれくらいのユーザーが増えたと思いますか? 1,000万人でしょうか、2,000万人でしょうか? 実は5,500万人以上のユーザーが増加しました。分かりやすく言うと、アメリカの人口の15%に相当する数字です。

Thumbnail 320

Thumbnail 330

同時接続ユーザー数はどのくらいだと思いますか?つまり、同時にアプリを使用しているユーザー数です。100万人、200万人、300万人でしょうか? 実際のピーク時の同時接続ユーザー数は1,500万人でした。 そして、これらのユーザーが生成するリクエスト数はどのくらいでしょうか? IPL(Indian Premier League)期間中、私たちのAPIゲートウェイで記録したリクエスト数は3億7,600万件でした。今日は、この2つの数字、つまり同時接続数と同時リクエスト数について詳しくお話ししたいと思います。

Thumbnail 350

Thumbnail 360

Thumbnail 380

しかしその前に、典型的なFantasyマッチの 流れについてご説明させていただきます。通常、私たちのプラットフォームでは複数の試合が並行して行われていますが、今日は1試合に焦点を当てて説明します。 試合開始の2~3日前に、その試合用のコンテストのリストを公開します。この時点で、ユーザーの皆さんがアプリに来始め、私たちが用意したコンテストに参加し始めます。試合開始30分前には、クリケットで 「Toss」と呼ばれる、他のスポーツと同様に先攻・後攻を決める行為があります。この30分間に多くのユーザーが参加し、実に70%のファンがこの時間帯に参加します。

Thumbnail 400

Thumbnail 430

そして試合が始まり、T20の試合は 約3~4時間続きます。この間、ユーザーは自分のランクやポイントを確認するためにプラットフォームを訪れ、私たちは可能な限り速くリーダーボードを更新し続けます。クリケットでは、1球ごとに5~10秒かかるため、数秒ごとにユーザーのランクとポイントを更新する必要があります。試合が終わると、勝者を発表し、ユーザーは 自分の獲得報酬を確認するためにプラットフォームを訪れます。

Thumbnail 440

では、このタイムライン上でのユーザートラフィックのパターンはどうなっているのでしょうか? これが私たちのトラフィックパターンです。特にこの30分間に注目してください。Tossの時点で何か特異なことが起き始めるのが分かります。私たちのビジネスでは、Tossでラインナップが発表され、どの選手が試合に出場するかが正確に分かった時点で興奮が始まります。テレビで実況が始まり、分析が行われ、皆が試合を見始め、多くのユーザーが私たちのプラットフォームにアクセスし始めます。トラフィックが急増し、試合が始まると、ユーザーは自分のポイントやランクを確認するために継続的にアプリを利用し続けます。

AWSを活用したインフラストラクチャの最適化

Thumbnail 500

Thumbnail 520

Thumbnail 540

では、AWSがどのように私たちを支援しているかについて、Satinderに説明を譲りたいと思います。ありがとうございます。このような大規模なスケールと短時間での高い同時接続数は、多くの課題をもたらします。私は上位3つの課題について説明し、その後詳細な議論に移りたいと思います。1つ目は、ピーク時のマッチデーにおけるスケールです。先ほど示したように、約46,500のインスタンスが稼働しており、その90%がSpotインスタンスです。163のApplication Load Balancerが1分間に1億4,500万以上のリクエストを処理しています。

Thumbnail 570

Thumbnail 580

これら2つの要因が組み合わさると、このような大量のインスタンスならではの課題が生じます。詳細なヘルスチェックと表面的なヘルスチェックの間で適切なバランスを見つける必要があります。これはデータベースにも波及します。166以上のAurora MySQLインスタンスがあり、最大のクラスターでは1分間に100万リクエストを処理しています。これは単一のクラスターの数字であり、全部で166のクラスターが存在します。最後になりますが、このようなトラフィック規模では、キャッシングは不可欠です。50以上のElastiCacheクラスターがあり、ピーク時には単一クラスターで1分間に400万以上のリクエストをサポートしています。

Thumbnail 600

2つ目の考慮事項はSpotインスタンスについてです。

インスタンスの90%がSpotインスタンスであることを考えると、可用性とコストの間で適切なバランスを見つける必要があります。時間をかけて様々な割り当て戦略を試験的に実施し、最終的にCapacity Optimizedが最適であると判断しました。最近では、Price Capacity Optimizedの実験も開始し、有望な結果が得られています。これをデフォルトの戦略にできるかどうか検討中です。現在は、Capacity OptimizedとPrice Capacity Optimizedの組み合わせを使用しています。現在、Spotフリートには140種類以上のインスタンスタイプが登録されており、属性ベースの選択がより効果的かどうかも実験的に検証しています。

Thumbnail 670

Thumbnail 690

重要なのは、大量のインスタンスが必要であり、コストとインスタンスの可用性のバランスを取ることが、このスケールの基盤となるということです。3つ目の重要な側面はセキュリティです。このような大規模なFantasy Sportsを運営する場合、正常なトラフィックと悪意のあるトラフィックを区別することが非常に重要になります。私たちは2つの対策を講じています。1つ目は多層防御アプローチで、脆弱性評価のためのAmazon Inspector、脅威管理プラットフォームとしてのAmazon GuardDuty、悪意のあるトラフィックをブロックするためのAWS WAFを含む、包括的なセキュリティ体制から始まります。

Thumbnail 750

Thumbnail 770

規模について考えると、新たな課題が浮かび上がってきます。その課題の1つは、ピークトラフィックが発生する際、そのトラフィックの大部分がISPを利用するモバイルデバイスから生じるということです。つまり、悪意のあるIPと正常なIPを識別する能力が非常に限られてしまいます。なぜなら、DDoS攻撃がISPを使用して接続するモバイルデバイスを通じて仕掛けられる可能性があるからです。 そこで、私たちは多くの自動化システムを構築しました。これはその一例で、不正なリクエストをリアルタイムで検出し、特定のIPアドレスから複数の不審なリクエストが確認された場合、そのIPアドレスを一時的にブロックするアクションを取ることができます。 この技術を使用することで、毎日何億もの悪意のあるリクエストをブロックすることが可能になりました。

Scalerシステム:予測に基づく自動スケーリング

Thumbnail 800

Thumbnail 810

Thumbnail 820

規模、コスト、セキュリティは、他のエンジニアリング課題に対処するための基盤となります。ここでSrijanに戻したいと思います。ありがとうございました。では、私たちが直面している主要なアーキテクチャ上の課題とその解決方法についてお話しします。 1つ目は、試合開始前の30分間に発生するインパルストラフィックです。 2つ目は、ユーザーに最高の体験を提供するため、Cricketの進行に合わせてリアルタイムでLeaderboardを更新し続けることです。 3つ目は大規模な障害への対処、そして4つ目はアプリ上でユーザーが見る試合をリアルタイムでパーソナライズすることです。

Thumbnail 830

最初の問題に焦点を当てると、これは5月26日のIPL決勝戦における1分あたりのリクエスト数の実際のスナップショットです。IPL(Indian Premier League)はインドの代表的なCricketトーナメントで、こちらでいうSuper Bowlに相当します。7時02分頃にラインナップが発表されると、これが変曲点となり、リクエスト数が急増し始めます。わずか3分間で1分あたり6,000万リクエストから2億7,000万リクエストまで増加するのです。このような急増に対して、通常のAuto-scalingでは対応できないことは想像に難くありません。そこで、私たちは事前に規模を予測し、今後数分間で発生するユーザー数に対応できるようにシステムをスケールする必要性を認識しました。そこで、Scalerというシステムを作ることにしました。その名の通り、このシステムは予想されるトラフィックに応じて適切にシステムをスケールするために使用されます。具体的には2つの役割があります:1つは今後15~30分間のトラフィックを予測すること、2つ目はジャストインタイムでシステムをスケールすることです。これから、アーキテクチャとこれら2つの機能についてより詳しく説明します。

Thumbnail 910

これが予測フローです。私たちは、過去数年間のトラフィックデータを使用してモデルを訓練しました。このモデルは、試合のタイプ、ユーザー数、コンテストへの参加パターンを分析します。これらすべてのデータポイントを使用してモデルを訓練し、このタイプの試合で、この日に、このような参加パターンがある場合、この時点でのトラフィックはどうなるべきかをモデルが理解し、次の15~30分間を適切に予測します。

Thumbnail 970

モデルは継続的にこれらの予測を行い、S3 Bucketに格納します。そこでLambdaがトリガーされ、 Consumerによって消費され、Amazon RDS Auroraデータベースに格納されます。この情報は上流システムで使用できる状態になります。次のフローは、この同時接続数の予測を使用して、今後15~30分間で来るユーザーに対してシステムを実際にスケールすることです。私たちは、このAuroraデータベースから継続的に読み取るSchedulerを実行しており、今後15~30分間でより多くのユーザーが来ることを検出すると、200以上のMicroservicesを含むすべてのシステムに対して1分あたりのリクエスト数を計算します。

Thumbnail 1030

Thumbnail 1040

各システムが受け取るリクエストは異なるため、予測された同時接続数に基づいて計算を行います。そして、コアエンジンに指示して、 AWS APIとEGに対して、予想されるトラフィックに応じてシステムをスケールするよう伝えます。 私たちは、この2年間このシステムを使用してきたことを誇りに思っています。これは運用を自動化するための事実上の標準システムとなっています。1,600万回以上(月間約75万回)のスケーリングを実施し、さらに重要なことに、開発者の運用時間を10万時間以上節約し、彼らの満足度を高めることができました。

Thumbnail 1080

Scalerは開発者にとって身近な存在となっているため、さらに彩りを添えるための新機能を開発しています。まず、プッシュ通知や選手の怪我、雨天などによる試合の遅延といった予期せぬイベントに対応する機能を導入しています。これらのイベントは既存の予測に影響を与える可能性があり、こうした予期せぬ事態は予測に組み込まれていない可能性があるためです。2つ目の機能は、ルールベースのエンジンの提供です。システムごとに異なる特性があり、カスタムロジックが必要になる可能性があるため、各開発者が予測に基づいて必要な容量を計算するためのルールを設定できるようにします。3つ目は、Amazon DynamoDB、Amazon Aurora、Amazon EMRなどの他のデータストアのサポートを追加し、開発者の運用時間をさらに削減することです。

リアルタイムLeaderboardの実現:Saltingによる並列処理

Thumbnail 1150

Thumbnail 1180

Thumbnail 1200

次に取り組む課題は、リアルタイムLeaderboardです。 具体的には、2,000万のチームを数秒ごとにランク付けする必要があります。なぜなら、クリケットでは1プレイが5〜10秒ごとに行われ、実際の試合の進行に合わせて、コンテストに参加しているユーザーのポイントとランクを更新し続ける必要があるからです。これが、数秒ごとに更新しているLeaderboardの画像とGIFです。 課題の詳細とその解決方法について説明する前に、まず全体的なアーキテクチャを理解しましょう。 はじめに、ユーザーがこの試合のために作成したすべてのチームのデータが保存されているTeam Serviceがあります。次にContest Serviceがあります。

Thumbnail 1230

このContest Serviceには、ユーザーがこの試合に参加したコンテストのすべてのデータが保存されています。試合が始まると、ユーザーはチームの編集やコンテストへの参加ができなくなります。このデータをログに記録し、1回限りの処理として3つのバケットのいずれかにダンプします。 Fantasy Point Serviceと呼ばれるサービスがあり、これは実際の試合イベントを理解する役割を担っています。例えば、オーストラリア対インドの試合で選手がボウリングやバッティングを行う場合、このサービスは実際の試合からイベントを取得し、各選手のポイントを計算します。

Thumbnail 1280

Thumbnail 1290

このデータはKafkaに送られ、すべての処理が行われるSpark Streamingクラスターがそれを購読します。このSpark Streamingクラスターは、Amazon S3に保存されているデータにもアクセスできます。クラスターは継続的にイベントを購読し、競技データを処理し、前のスライドでお見せしたLeaderboardをユーザーに表示するためにLeaderboard Serviceに書き込みます。

まず、私たちが直面している問題の規模について理解しましょう。典型的なIPLの試合では、100万以上のコンテストが運営されています。2人のプレイヤーが競い合う2人用コンテストから、2,000万人が参加する大規模なコンテストまで、実にさまざまです。この試合のコンテストチームデータは約200ギガバイトにも及び、2,000万人規模のメガコンテストだけでも約80ギガバイトのデータ量になります。参考までに、m5.8xlargeのような十分に大きなマシンでもRAMは128ギガバイトです。

Thumbnail 1340

メガコンテストに焦点を当てると、いくつかの問題に直面します。1つ目はメモリ不足の問題です。メガコンテストが存在するSparkエグゼキュータは、処理に必要な最低限のメモリしか持っていないことがよくあります。ガベージコレクションの遅延や、同じエグゼキュータで並行して実行される試合の計算により、十分な処理メモリが確保できず、イテレーションのやり直しが必要になります。その結果、各ボールごとのポイント更新が遅れ、ユーザー体験が低下してしまいます。2つ目は、メガコンテストがどのエグゼキュータノードにも存在する可能性があるため、クラスター全体をスケールアップする必要があり、大きなコストがかかることです。3つ目は、メガコンテストを扱うエグゼキュータが2,000万行を単独でソートしなければならない一方で、小規模なコンテストを扱う他のエグゼキュータはより早く処理を終えてしまうため、効果的な並列処理が活用できないことです。

Thumbnail 1430

Thumbnail 1440

Thumbnail 1470

Thumbnail 1500

これらの問題を、Saltingという古くからある手法を使って解決しました。 Spark Streamingで何が起きているのか、段階を追って説明しましょう。第1段階では、データが全パーティションに分散しています。パーティション1にはコンテスト1とコンテスト2のデータがあり、パーティション2にはコンテスト1、コンテスト2、コンテスト4のデータがある、といった具合です。 最初のステップとして、Saltingを使用してSalt Keyという新しいカラムを導入し、大規模なコンテストを分割します。例えば、C1がメガコンテストの場合、C1_1、C1_2などの複数のチャンクに分割します。 次のステップでは、Salt Keyをグループ化パラメータとして使用し、すべてのデータをシャッフルして再パーティショニングします。

Thumbnail 1540

これにより、パーティション1にはC1_1の全ルールが存在し、同様にパーティション2にはC1_2が存在する、という具合になります。つまり、大規模なコンテストが複数の小さなチャンクに分割され、各チャンクの全行が1つのパーティションにのみ存在するようになりました。これにより、各パーティションで特定のコンテストの特定のSalt Keyに対するソートが容易になりました。

Thumbnail 1610

その後、各パーティションから各コンテストの上位2,000位を抽出し、それらをマージしてLeaderboardサービスに格納し、ユーザーに提供します。アプリでは各コンテストの上位2,000位までを表示しており、これらの上位2,000行は任意のパーティションに存在する可能性があります。そのため、各パーティションから上位2,000位を抽出し、マージ、ソートして、10秒ごとに新しいイベントに対してLeaderboardサービスに書き込みを行い、ユーザーに期待される体験を提供しています。この方法により、可能な限りの並列化を活用でき、計算時間を数分から数秒に短縮できたことを嬉しく思います。これによって、ユーザーはテレビでクリケットの試合を観戦しながら、アプリでもリアルタイムにエキサイティングな体験を楽しむことができるようになりました。

システムのレジリエンシー:障害対策と影響最小化

Thumbnail 1650

人気の高い試合中にシステムに発生する膨大なスケールによって、どのような課題に直面するかを確認してきました。しかし、ソフトウェアには障害がつきものであり、どんなに準備をしていても、これらの障害を防いだり、適切に対処したりするメカニズムが必要です。これは私たちのアーキテクチャの理念の一部であり、既知・未知を問わず、システムが障害に対して十分な回復力を持つことを常に確保しています。

Thumbnail 1670

Thumbnail 1690

レジリエントなシステムが必要な第一の理由は、過剰なリクエストに対処するためです。トラフィックを予測する方法は多くありますが、それでも特定の状況では、予想や想定をはるかに超えるトラフィックが発生することがあります。第二の理由は、より迅速な回復メカニズムが必要だからです。30分間という限られた時間枠の中で、ユーザーに最高の体験を提供しなければならず、また、この時間帯は私たちにとって収益の重要な期間でもあります。そのため、何か問題が発生した場合は、できるだけ早く元の状態または正常な状態に戻す必要があります。

Thumbnail 1730

第三の理由は、影響を最小限に抑えることです。回復のためのメカニズムがあっても、それが機能しない場合、この影響を制限して、ユーザーの一部にのみ影響が及ぶようにし、大多数のユーザーがプラットフォーム上でコンテストを楽しめるようにする必要があります。以降のスライドでは、私たちの重要なサービスやシステムの例を紹介し、アーキテクチャにおけるレジリエンシーの3つの理由すべてにどのように対応しているかを説明します。

Thumbnail 1760

Thumbnail 1770

まずは過剰なリクエストへの対処から始めましょう。incoming trafficに対して、すべてのアプリケーションを適切なタイミングでスケールアップする自動化システムがあることを見てきました。しかし、何らかの理由で予想以上のトラフィックが発生することがあります。これがシステムの簡略化された図です:API Gatewayがあり、Service Poolが別のService Barと通信し、Service Bar用のデータストアがあります。しかし、過剰なトラフィックにより、このデータストアは適切にプロビジョニングされていません。キャパシティが不足しているか、オーバーロードになっているか、あるいは特定のスロークエリが問題を引き起こしている可能性があります。

Thumbnail 1790

Service Barがこれを検知すると、最大容量に達していることを示し、これ以上のリクエストを適切にドロップします。このService Barは次にService Twoに通信し、Service Twoもまた容量が一杯でこれ以上リクエストを受け付けられないことを示します。Gatewayはこれを理解し、過剰なリクエストのドロップを開始します。Reactive Programmingの核となるこのシンプルなBack-pressureメカニズムは、予想以上のトラフィックが発生する状況で私たちの助けとなっています。

このような状況では、インフラストラクチャのキャパシティを増強するために、対応時間とオペレーターの介入が必要になります。過剰なリクエストのみが破棄され、大半のリクエストは引き続き処理されます。私たちのエコシステムとサービスメッシュ全体に、Circuit Breakerを実装しています。Circuit Breakerが必要な理由は、重要度の異なるシステムが存在するためです。その名前が示す通り、リクエストを送信するサービスが、レイテンシーやエラーの閾値が許容範囲を超えていると判断した場合、自身を保護しようとします。

Thumbnail 1870

Thumbnail 1890

Thumbnail 1900

例えば、API Gatewayがサービスfで非常に高いレイテンシーや高いエラー率を検知した場合、Circuit Breakerが作動し、一定時間接続が遮断されます。 しばらくしてから再接続を試み、下流のサービスが復旧したかどうかを確認します。これはGatewayとサービス間だけでなく、サービス間 やサービスとデータストア間でも同様です。後ほど、アプリケーションとデータストア間のCircuit Breakerが、システムの健全性を維持し、システム全体のダウンを防ぐのに役立つ例をご紹介します。

2番目の例として挙げた迅速な復旧について、最適な例がTeamサービスです。Teamサービスでは、ユーザーがプラットフォーム上でファンタジーチームを作成し、ビジネスユーザーは最後の瞬間まで修正、編集、最適なチーム選択を続けたいと考えています。通常、この時間枠は30分ですが、雨天や、時間枠が5分まで短縮される場合、ピッチコンディション、試合条件、ラインナップなど、多くの要因が変化します。ユーザーはプラットフォームに戻って再度編集を行いたいと考えます。このサービスは1秒あたり90,000から92,000という非常に高いリクエスト数を処理します。分かりやすく言うと、最大規模のクリケットスタジアムの収容人数は約100,000人です。そのスタジアムの全員が同時にチームを編集しようとし、各編集を保存する必要がある状況を想像してください。保存できないとユーザーの信頼を損ね、フェアプレイとは言えません。

Thumbnail 1990

Thumbnail 2000

Thumbnail 2010

このシステムは非常に重要なため、適切な復旧メカニズムが必要です。ここでは、シンプルなActive-Passiveセットアップを実装しています。Aerospike Clusterを使用したActiveデータストアがあり、Activeから Passiveデータストアへの二重同期書き込みを行い、これらの ActiveレコードをフィルタリングしてPassiveに書き込むカスタムループを作成しています。同時に、PassiveもActiveに対して同様のループを持っています。これは、 Activeのキャパシティに問題が発生した場合、数秒以内にPassiveに切り替えられるようにするためです。Passiveに切り替わっても、すべてのデータがPassiveに存在し、このループが継続的に実行されているため、ユーザーエクスペリエンスへの影響はありません。

このシステムは、250,000の書き込みスループットまでパフォーマンステストを実施しています。また、非本番環境で広範なカオステストを行い、これらのシナリオを常に再現して、この復旧メカニズムが機能することを確認しています。本番環境でもドリルを実施し、ActiveからPassiveへの切り替えがデータ損失なく数秒以内に行われることを確認しています。XDRメカニズムや非同期書き込みだけに依存せず、ActiveとPassive間のデータ遅延やデータ損失が一切ないことを完全に確実にしたいと考えています。ユーザーがチームが保存されなかった、あるいはチームを編集できなかったと主張した場合、それは悪いユーザーエクスペリエンスとなり、すべてのラウンドやコンテストについてユーザーに全額返金が必要になる可能性があります。この迅速な復旧メカニズムは、予期せぬトラフィックや緊急事態の際に特に効果を発揮します。

Thumbnail 2120

3番目に私たちが話したのは、優れたシステムを設計しているにもかかわらず、問題が発生する可能性があるため、その影響を最小限に抑える必要があるということです。Walletサービスを例に挙げて説明しましょう。 Walletは、その名の通り、ユーザーのアカウント残高を管理し、入出金のすべての取引を追跡する台帳です。ユーザーはより多くのコンテストに参加するために入金したり、既存の残高でコンテストに参加したり、プラットフォーム上でさまざまな小額の購入を行ったりします。また、試合が中止された場合は、ユーザーが将来のコンテストに参加できるよう、Walletに返金を処理します。

Thumbnail 2210

Thumbnail 2230

常に大量の取引が非常に高いスループットで発生しており、単一のクルスターで提供できる以上のパフォーマンスが必要です。残高チェックを含めて、1クラスターあたり毎秒13,000から14,000件もの取引が発生し、総RPMは約135,000に達します。 私たちは、どのユーザー情報とアカウント残高がどのShardに存在するかを追跡するShard Metaを使用してデータストアのShardingを実装しました。Walletサービスはこれと通信して、どのShardが取引を処理すべきかを素早く判断します。 これにより、高いスループットを管理しながら、アカウント残高の正確性を維持することができます。

Thumbnail 2300

IPLの試合中は、連続する試合によって追加の課題に直面します。3時間の試合が終わり、別の人気のある試合が始まるとき、重複する時間帯が発生します。この30分の時間帯で、ユーザーは入金してコンテストに参加する一方で、前の試合の勝者が決定されています。 勝者は数営業日待つのではなく、即座にアカウントに報酬が支払われる即時の満足感を得られます。これは、Winner Dispersalシステムが他の取引と並行して実行され、実質的にシステムのスループットが2倍になることを意味します。

Thumbnail 2360

水平・垂直スケーリングでこの増加した負荷に対応できますが、課題は、常に入金と出金で更新が必要な単一ユーザーのアカウント残高の管理にあります。同じユーザーが賞金を受け取りながらコンテストに参加しようとする状況では、特定のShardでレイテンシーやキャパシティの問題が発生する可能性があります。 これが発生すると、アプリケーションのCircuit Breakerが作動し、その特定のShardに対してCircuitを切断します。例えば、10個のShardがある場合、90%のユーザーは影響を受けずにコンテストに参加してプラットフォームでプレイを続けることができます。これにより、影響を受けるShardが回復するか、より大きなキャパシティのクラスターにアップグレードされる間、影響範囲をユーザーの一部に限定することができます。このように、Shardingは不利な状況での影響を最小限に抑えるのに役立っており、これが私たちのシステムのレジリエンシーに対するアプローチです。

パーソナライゼーションと今後の展望

Thumbnail 2420

システムのレジリエンシーについて説明したところで、言及された4番目の課題である個人化に移りましょう。私たちは皆、多くのオンライン製品やEコマースウェブサイトを利用しています。 今日では個人化が重要であり、2,000万人以上のユーザーに個別のエクスペリエンスを提供したいと考えています。なぜなら、この大規模なユーザーベース全体で、ペルソナが大きく異なるからです。私たちは、ユーザーがプレイできる試合、レコメンデーション、各試合のコンテスト、決済の流れ、割引などを個人化しています。

Thumbnail 2470

私たちにとって特に印象的な例が、Match Personalizationです。これはアプリのホームページで最初に行われるインタラクションであり、1,500万人以上のユーザーに対してほぼリアルタイムで実行されています。数年前まではこのレベルに達していませんでしたが、いくつかの課題に直面していました。最初の課題は、進化し続けるユーザーの好みへの対応でした。大規模なユーザーベースを持つ中で、ユーザーは好きなスポーツ、応援するチーム、フォローする選手、さらには新しいトーナメントが人気を集めることで変化するトーナメント形式など、その嗜好を変化させていきます。これらの絶えず進化するユーザーの好みに対応し、配慮する必要があります。そうでなければ、パーソナライゼーションは効率的にも効果的にも機能しないからです。

Thumbnail 2500

Thumbnail 2520

二つ目の課題は、私たちにとって関連性は新しさとイコールではないということです。試合を開始時間で並べ替えるのは簡単ですが、それがユーザーにとっての関連性を保証するわけではありません。三つ目の課題は、バッチ予測に関するものでした。このほぼリアルタイムの推論とレコメンデーションシステムを導入する前は、バッチ処理でレコメンデーションを行っていましたが、プラットフォーム上で毎日約150から200の試合が行われるため、これらはすぐに古くなってしまいました。次の20~30分の間にどのユーザーがプラットフォームにアクセスしてレコメンデーションを必要とするかわからないため、バッチ予測は費用対効果が良くありませんでした。

Thumbnail 2560

Thumbnail 2600

四つ目の課題は、Sparkを使用した異種コンピューティングでした。私たちは、可能な限り多くのインフラを最小のコストで活用したいと考えているため、多様化戦略を信じています。これらの課題を解決し、現在の状態を実現するために、私たちはDarwinと呼ばれる大規模なパーソナライゼーションを行うための社内システムを構築しました。これはRAY serveをベースにした簡素化されたシステムです。RAY serveをご存じない方のために説明すると、これはオンライン推論APIを構築し、機械学習モデルやアプリケーションを実行できるライブラリです。

Thumbnail 2630

Thumbnail 2650

私たちはRAY serveを選択し、期待されるスループットとレイテンシーを管理するために数多くの修正を加えたカスタマイズバージョンを使用しています。その上に、これらのワークロードを最も効率的な方法で分散させる計算マネージャーを作成しました。これはマルチテナントシステムであり、レコメンデーションのワークロードがMatch Personalizationのワークロードと干渉しないようになっています。データサイエンスチームが構築するこれらのモデルはすべて、ユーザー情報、試合情報、過去の履歴、ユーザーコンテスト、そして活用可能な関連するユーザーデータを含むFeature Storeと連携して実行されます。

Thumbnail 2670

Match Personalizationについては、ユーザーにデフォルトの試合情報を提供するサービスがあります。このパーソナライゼーションエンジンを大規模に使用し、特定のモデルを実行して、目的のレコメンデーションを並べ替えます。RAYを使用することで、4ミリ秒という低レイテンシー、10億回の推論を実現し、このシステム全体のP99は50ミリ秒という低さを達成しています。

Thumbnail 2720

Thumbnail 2730

Thumbnail 2740

コストの観点からお話しさせていただきますと、コストは重要な要素ですが、この規模で実現できているのは1日わずか50ミリ秒というレベルです。これが実際の動作です。右側に表示されているのが私たちのホームページで、そこにマッチリストが表示され、レコメンデーションに基づいて常に並び替えが行われています。これがデフォルトのマッチ順序でのユーザーリクエストです。Feature Storeから特徴量を取得し、計算を行い、Darwinのプラットフォームに配置します。エンジンが実行され、スコアを取得し、そのスコアに基づいて並び替えを行います。これは各コンテストに参加する際の各マッチ参加時に発生しており、常に更新されることで、ほぼリアルタイムのパフォーマンスを実現しています。

次に私たちが検討し実験しているのは、このパーソナライゼーションエンジンをエッジレイヤーに移行することです。これにより50ミリ秒未満での処理が可能になります。私たちが見ている規模とファンタジープレイヤーが求めるユーザー体験を考えると、1ミリ秒という時間も非常に重要なのです。これまで私たちが何をしているのか、どのようにアーキテクチャを解決してきたのかについてお話ししてきましたが、最後に、今後の展望についてお伝えしたいと思います。

Thumbnail 2830

まず、私たちはファンタジースポーツという常に進化し続ける領域にいます。すでに12のスポーツをサポートしていますが、プラットフォーム上でユーザーを継続的に惹きつけ、より多くのフォーマットとスポーツをサポートしていきたいと考えています。そのためには現在、新しい開発と新しいシステムが必要です。そこで、ビジネス成長のための実験を支援するプラットフォームソリューションの構築に投資しています。これらはファンタジースポーツに特化したものになりますが、このようなプラットフォームを構築することで、新機能や新フォーマットをより迅速にエンドユーザーに提供し、Product Market Fitを確認し、さらなる改善を図ることができます。

Thumbnail 2850

第二に、私たちは常により高い同時接続数を目指しています。確かに1,500万という数字は、他のオンラインゲームと比べても非常に大きな数字です。他のゲームでは、これほどの同時接続ユーザー数は見られず、むしろこの数字は世界中に分散したデイリーアクティブユーザー数として見られる程度です。しかし私たちにとって、この数字はさらに大きくなっていきます。3月に開始されるIPL 25ではさらに増加するでしょう。そのため、私たちは常にブレークポイントがどこにあるのか、単一障害点はどこにあるのか、それらをより適切に特定してアーキテクチャ設計をどのように改善できるのかを検討しています。

Thumbnail 2890

第三に、現在私たちが積極的に取り組んでいるのは、マルチシャード化されたデータストアの管理です。これは開発工数を要する運用上の大きなオーバーヘッドとなっています。ツーリングプラットフォームを構築し、スケーラブルなシステムと統合してきましたが、特に多くのトランザクションシステムを扱う中で、データストアのスケールアップとダウンはシームレスなプロセスとは言えません。そこで、Aurora Limitless DBのようなソリューションを検討し、現在の作業量を最大70%まで削減できないか模索しています。

Thumbnail 2930

最後になりますが、誰もが注目しているAIについてお話しします。 Dream11のプロダクト側では、カスタマーサービスやAIコーチングアシスタントなど、エンドユーザー向けのさまざまなユースケースを検討しています。しかし、テクノロジーチームとして特に力を入れているのが品質保証です。私たちは、テストケースの自動生成や一貫性のあるSynthetic Dataの生成にAIを活用する方法を模索しています。200以上のサービスがあり、何千ものユーザーフローに一貫性のあるデータが必要となる中で、これは大きな課題となっています。これが来年に向けて取り組んでいく課題です。

Thumbnail 2990

このセッションが皆様にとって有意義なものとなり、重要な学びを得ていただけたことを願っています。 お時間をいただき、ありがとうございました。それでは質疑応答に移らせていただきます。


※ こちらの記事は Amazon Bedrock を利用することで全て自動で作成しています。
※ 生成AI記事によるインターネット汚染の懸念を踏まえ、本記事ではセッション動画を情報量をほぼ変化させずに文字と画像に変換することで、できるだけオリジナルコンテンツそのものの価値を維持しつつ、多言語でのAccessibilityやGooglabilityを高められればと考えています。

Discussion