すべてのプロダクト
Search
ドキュメントセンター

Tair (Redis® OSS-Compatible):TairZsetを使用して多次元リーダーボードを実装する

最終更新日:Sep 12, 2024

TairZsetは、Alibaba Cloudによって開発されたデータ構造です。 DOUBLE型のスコアデータを256のディメンションに対してソートできます。

Redis ZSETの問題

オープンソースのRedisのSorted Set (またはZSET) データ構造では、DOUBLEタイプのスコアデータに基づいて、単一の次元で要素をソートできます。 たとえば、IEEE Standard For Floating-Point Arithmetic (IEEE 754) 標準を使用してスコアデータを連結し、多次元ソートを実装できます。 ただし、この方法は、複雑なロジック、精度の低下、およびZINCRBYコマンドが使用できないことによって制限されます。

TairZsetの紹介

多次元ソートの実装を支援するために、Alibaba CloudはTairZsetデータ構造を開発しました。 上記の方法と比較して、TairZsetには次の利点があります。
  • DOUBLEタイプのスコアを最大256のディメンションに基づいてソートできます。 スコアは、優先順位に基づいて左から右に表示されます。

    多次元ソートでは、左スコアは右スコアよりも高い優先度を有する。 例として、score1#score2#score3形式の3次元スコアの比較を取り上げます。 TairZsetは、複数の3次元スコアのスコアを比較し、スコアが等しい場合にのみスコア2に進む。 スコアが等しくない場合、スコアのランキングは、関係する3次元スコアのランキングを表す。 同じ論理によって、score2が等しい場合にのみscore3が比較される。 すべてのスコアが等しく、同じことがスコア2およびスコア3に当てはまる場合、関与する多次元スコアはASCIIソート順にランク付けされる。

    わかりやすくするために、数値記号 (#) を小数点 (.) として想像できます。 このように、0#99 < 99#90 < 99#99は、0.99 < 99.90 < 99.99として見ることができる。

  • EXZINCRBYコマンドをサポートします。 現在のデータを取得し、データに増分を適用してから、データをRedisデータベースに書き戻す操作を実行する必要がなくなりました。
  • ネイティブRedis ZSETで利用可能なものと同様のAPIをサポートします。
  • 実装できます 通常のリーダーボード および 分散リーダーボード
  • オープンソースのTairJedisクライアントをサポートします。 TairJedisクライアントの詳細については、alibabacloud-tairjedis-sdkをご覧ください。 データのエンコード、デコード、カプセル化を行うことなく、TairJedisクライアントを使用できます。 オープンソースコードを参照して、他のプログラミング言語のクライアントをカプセル化することもできます。
説明 このトピックで使用されるTairZsetコマンドの詳細については、「exZset」をご参照ください。

シナリオ

ゲーム、アプリケーション、メダルのリーダーボードでは、次のランキング要件が一般的です。

  • 指定されたスコア範囲に基づくメンバークエリのサポート、作成、読み取り、更新、削除 (CRUD) 操作、および逆ソート。
  • ソート結果の迅速な取得。
  • 実装するスケーラビリティ 分散リーダーボード現在のデータシャードのストレージまたは計算能力が不十分な場合、ワークロードを他のデータシャードにオフロードできます。

TairZsetを使用してメダルリーダーボードを実装する

ランク参加者Gold medal金メダルSilver medalシルバーメダルBronze medalブロンズメダル
1HTTP ステータスコードが322116
2B252921
3C20712
4D14416
5E132118
6F131714

メダルリーダーボードでは、参加者は獲得した金メダル、銀メダル、銅メダルの数でソートされます。 金メダルの数が同じ場合、それらは彼らが勝った銀メダルの数によって分類されます。 銀メダルの数も同じであれば、彼らが勝った銅メダルの数でソートされます。 たとえば、参加者EとFは同じ数の金メダルを持っていますが、参加者Eは参加者Fよりも多くの銀メダルを持っています。この場合、参加者Eは参加者Fよりも上位にランク付けされています。

次のコードを実行して、依存関係をインストールできます。 この例では、TairJedis用のAlibaba Cloud SDKが使用されています。 詳細については、alibabacloud-tairjedis-sdkをご覧ください。

<dependency>
    <groupId>com.aliyun.tair</groupId>
    <artifactId>alibabacloud-tairjedis-sdk</artifactId>
    <version>1.6.0</version>
</dependency> 

サンプルコード:

JedisPool jedisPool = new JedisPool();
// リーダーボードを作成します。
LeaderBoard lb = new LeaderBoard("leaderboard", jedisPool, 10, true, false);

// 金メダルの数で参加者をランク付けします。 金メダルの数が同じ場合は、銀メダルの数で参加者をランク付けします。 銀メダルの数も同じ場合は、参加者を銅メダルの数でランク付けします。
// 金メダル銀メダル銅メダル
lb.addMember("A" 、32、21、16);
lb.addMember("D" 、14、4、16);
lb.addMember("C" 、20、7、12);
lb.addMember("B" 、25、29、21);
lb.addMember("E" 、13、21、18);
lb.addMember("F" 、13、17、14);

// 参加者Aのランクを取得します。lb.rankFor("A"); // 1

// 上位3名の参加者を取得します。
lb.top(3);
// [{"member":"A","score":"32#21#16","rank":1},
// {"member":"B" 、"score":"25#29#21" 、"rank":2} 、// {"member":"C","score":"20#7#12","rank":3}]

// リーダーボード全体を取得します。
lb.allLeaders();
// [{"member":"A","score":"32#21#16","rank":1},
// {"member":"B" 、"score":"25#29#21" 、"rank":2} 、// {"member":"C" 、"score":"20#7#12" 、"rank":3} 、// {"member":"D" 、"score":"14#4#16" 、"rank":4} 、// {"member":"E" 、"score":"13#21#18" 、"rank":5} 、// {"member":"F","score":"13#17#14","rank":6}] 

TairZsetを使用して、時間、日、週、月、またはリアルタイムでリーダーボードを実装する

キーの月次リーダーボードを実装する場合は、月情報をインデックスとして使用する必要があります。

さまざまな時間範囲のリーダーボードは、TairZsetデータ構造によって提供されるマルチレベルインデックスを使用することによって実装できます。 この例では、月のすべてのデータがjulyZsetという名前のキーに格納されます。 次のコードは、サンプルデータをキーに書き込む方法を示しています。

EXZINCRBY julyZset 7#2#6#16#22#100 7#2#6#16#22_user1
EXZINCRBY julyZset 7#2#6#16#22#50 7#2#6#16#22_user2
EXZINCRBY julyZset 7#2#6#16#23#70 7#2#6#16#23_user1
EXZINCRBY julyZset 7#2#6#16#23#80 7#2#6#16#23_user1 
説明
  • 7#2#6#16#22#100は、スコアが7月6日の16:22に100に更新されることを示す。 日付は7月の第2週に属します。
  • 7#2#6#16#22_user1は、この時点でスコアが更新されたユーザを示す。 プレフィックスは、ユーザー名に時間が追加されたことを示します。
リーダーボードタイプコマンドと出力
リアルタイムの毎時リーダーボード。 このタイプのリーダーボードには、現在時刻の1時間前にスコアが更新されたメンバーが含まれます。 たとえば、現在の時刻が16:23である場合、ランキングには15:23から16:23の範囲でスコアが更新されたメンバーが含まれます。
説明 ランキング結果に頻繁にアクセスする場合は、結果をキャッシュすることを推奨します。

Command:

EXZREVRANGEBYSCORE julyZset 7#2#6#16#23#0 7#2#6#15#23#0

出力:

1) "7#2#6#16#22_user1"
2) "7#2#6#16#22_user2" 
特定の時間のリーダーボード。 たとえば、16:00 ~ 17:00の時間範囲内にスコアが更新されたメンバーを含むリーダーボードを照会できます。

Command:

EXZREVRANGEBYSCORE julyZset 7#2#6#17#0#0 7#2#6#16#0

出力:

1) "7#2#6#16#22_user1"
2) "7#2#6#16#22_user2" 
毎日のリーダーボード。 たとえば、7月5日にデータが生成されたリーダーボードを照会できます。

クエリの前に、次のコマンドを使用して、7月5日に生成されたデータレコードを挿入します。

EXZINCRBY julyZset 7#2#5#10#23#70 7#2#5#10#23_user1

出力:

"7#2#5#10#23#70"

Command:

EXZREVRANGEBYSCORE julyZset 7#2#6#0#0#0 7#2#5#0#0#0

出力:

1) "7#2#5#10#23_user1"
毎週のリーダーボード。 たとえば、7月の第2週のリーダーボードをクエリできます。

Command:

EXZREVRANGEBYSCORE julyZset 7#3#0#0#0#0#0 7#2#0#0#0#0

出力:

1) "7#2#6#16#22_user1"
2) "7#2#6#16#22_user2"
3) "7#2#5#10#23_user1" 
毎月のリーダーボード。 たとえば、7月のリーダーボードを照会できます。

クエリの前に、7月20日に生成されたデータレコードを挿入します。

EXZINCRBY julyZset 7#4#20#12#20#50 7#4#20#12#20_user1

出力:

"7#4#20#12#20#50"

Command:

EXZREVRANGEBYSCORE julyZset 7#6#0#0#0#0#0 7#0#0#0#0

出力:

1) "7#4#20#12#20_user1"
2) "7#2#6#16#22_user1"
3) "7#2#6#16#22_user2"
4) "7#2#5#10#23_user1"