TairZsetは、Alibaba Cloudによって開発されたデータ構造です。 DOUBLE型のスコアデータを256のディメンションに対してソートできます。
Redis ZSETの問題
オープンソースRedisのSorted Set (またはZSET) データ構造では、DOUBLE型のスコアデータに基づいて複数のディメンションではなく、1つのディメンションでのみ要素をソートできます。 たとえば、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コマンドをサポートします。 現在のデータを取得し、データに増分を適用してから、データをTairに書き戻す操作を実行する必要がなくなりました。
オープンソースのRedis Zsetと同様のAPIをサポートします。
実装できます 通常のリーダーボード および 分散型リーダーボード マルウェアを検出します。 マルウェアが検出されると、この機能はアラートイベントを生成します。
オープンソースのTairJedisクライアントをサポートします。 TairJedisクライアントの詳細については、GitHubをご覧ください。 データのエンコード、デコード、カプセル化を行うことなく、TairJedisクライアントを使用できます。 オープンソースコードを参照して、他のプログラミング言語のクライアントをカプセル化することもできます。
このトピックで使用されるTairZsetコマンドの詳細については、「exZset」をご参照ください。
シナリオ
ゲーム、アプリケーション、メダルのリーダーボードでは、次のランキング要件が一般的です。
指定されたスコア範囲に基づいて、作成、読み取り、更新、削除 (CRUD) 操作、逆ソート、およびメンバークエリをサポートします。
ソート結果の迅速な取得。
実装するスケーラビリティ 分散型リーダーボード 現在のデータシャードのストレージまたは計算能力が不十分な場合、ワークロードを他のデータシャードにオフロードできます。
TairZsetを使用してメダルリーダーボードを実装する
ランク | 参加者 | 金メダル | シルバーメダル | 銅メダル |
1 | A | 32 | 21 | 16 |
2 | B | 25 | 29 | 21 |
3 | C | 20 | 7 | 12 |
4 | D | 14 | 4 | 16 |
5 | E | 13 | 21 | 18 |
6 | F | 13 | 17 | 14 |
メダルリーダーボードでは、参加者は獲得した金メダル、銀メダル、銅メダルの数でソートされます。 金メダルの数が同じ場合、それらは彼らが勝った銀メダルの数によって分類されます。 銀メダルの数も同じであれば、彼らが勝った銅メダルの数でソートされます。 たとえば、参加者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();
// Create a leaderboard.
LeaderBoard lb = new LeaderBoard("leaderboard", jedisPool, 10, true, false);
// Rank the participants by the number of their gold medals. If the number of gold medals is the same, rank the participants by the number of their silver medals. If the number of silver medals is also the same, rank the participants by the number of their bronze medals.
// Gold medal Silver medal Bronze medal
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);
// Retrieve the rank of Participant A.
lb.rankFor("A"); // 1
// Retrieve the top 3 participants.
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}]
// Retrieve the entire leaderboard.
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:
出力:
|
特定の時間のリーダーボード。 たとえば、16:00 ~ 17:00の時間範囲内にスコアが更新されたメンバーを含むリーダーボードを照会できます。 | Command:
出力:
|
毎日のリーダーボード。 たとえば、7月5日にデータが生成されたリーダーボードを照会できます。 | クエリの前に、次のコマンドを使用して、7月5日に生成されたデータレコードを挿入します。
出力:
Command:
出力:
|
毎週のリーダーボード。 たとえば、7月の第2週のリーダーボードをクエリできます。 | Command:
出力:
|
毎月のリーダーボード。 たとえば、7月のリーダーボードを照会できます。 | クエリの前に、次のコマンドを使用して、7月20日に生成されたデータレコードを挿入します。
出力:
Command:
出力:
|