TairJedis クライアントを使用すると、exZset データ構造を使用して分散型リーダーボードを実装できます。単一のキーを操作するだけで済みます。Tair は、データと計算タスクを複数のサブキーに自動的に分散します。デフォルトでは 10 個のサブキーが使用され、その詳細を管理する必要はありません。このソリューションは、100,000 人を超えるメンバーを持つリーダーボードを簡単に作成し、large キーやホットキーを回避するのに役立ちます。
背景情報
分散型リーダーボードを実装するには、正確なランキングメソッドと不正確なランキングメソッド (線形補間) の 2 つのソリューションがあります。
表 1. 分散型リーダーボードを実装するためのソリューション
ソリューション | 説明 |
正確なランキング (推奨) | データを計算のために異なるキーに分散します。クエリを実行するときは、各キーでターゲットデータのランクを見つけ、そのランクを合計します。 たとえば、3 つの基になるキーを使用するとします。リーダーボードを作成して 3,000 人のメンバーを挿入すると、Tair はこれらのメンバーを 3 つのサブリーダーボードに分散します。メンバー x のランクを見つけるには、FindRank(x) 操作で 3 つのサブリーダーボードにクエリを実行します。返されたランクが 124、183、156 の場合、メンバー x の実際のランクは 463 (124 + 183 + 156) です。
|
線形補間 (exZset では未実装) | このメソッドは、データをセグメントに分割します。各セグメントのメンバー数と最高ランクを記録します。セグメントの最小値と最大値の間にあるスコアについては、線形補間を使用してランクを推定します。
|
このソリューションは、正確なランキングメソッドを使用して分散型リーダーボードを実装します。このソリューションで使用される exZset コマンドの詳細については、「exZset」をご参照ください。
コード例
このソリューションには、Tair によって開発された TairJedis クライアントが必要です。
pom.xml 構成を追加します。
<dependency> <groupId>com.aliyun.tair</groupId> <artifactId>alibabacloud-tairjedis-sdk</artifactId> <version>5.3.1</version> </dependency>サンプルコード。
import io.valkey.JedisPool; import io.valkey.JedisPoolConfig; import com.aliyun.tair.tairzset.*; public class DistributedLeaderBoardExample { // インスタンスのエンドポイント、ポート、パスワード、およびその他の情報を構成します。 private static final int DEFAULT_CONNECTION_TIMEOUT = 5000; private static final int DEFAULT_SO_TIMEOUT = 2000; private static final String HOST = "<r-bp1mx0ydsivrbp****.redis.rds.aliyuncs.com>"; private static final int PORT = 6379; private static final String PASSWORD = "<Pass****word>"; private static final JedisPoolConfig config = new JedisPoolConfig(); // 分散型リーダーボードを構成します。 private static final int shardKeySize = 10; // 基になるサブリーダーボードの数。 private static final int pageSize = 10; // リーダーボードの各ページのメンバー数。 private static final boolean reverse = true; // この例では、メンバーは降順でソートされます。 private static final boolean useZeroIndexForRank = false; // この例では、ランクは 1 から始まります。 public static void main(String[] args) { JedisPool jedisPool = new JedisPool(config, HOST, PORT, DEFAULT_CONNECTION_TIMEOUT, DEFAULT_SO_TIMEOUT, PASSWORD, 0, null); // 分散型リーダーボードを作成します。この例では、キーの名前は distributed_leaderboard です。 DistributedLeaderBoard dlb = new DistributedLeaderBoard("distributed_leaderboard", jedisPool, shardKeySize, pageSize, reverse, useZeroIndexForRank); // 金メダルの数が同じ場合は、銀メダルの数でソートします。銀メダルの数も同じ場合は、銅メダルの数でソートします。 // 金 銀 銅 dlb.addMember("A", 32, 21, 16); dlb.addMember("D", 14, 4, 16); dlb.addMember("C", 20, 7, 12); dlb.addMember("B", 25, 29, 21); dlb.addMember("E", 13, 21, 18); dlb.addMember("F", 13, 17, 14); // A のランクを取得します。 dlb.rankFor("A"); // 1 System.out.println(dlb.rankFor("A")); // 上位 3 件を取得します。 dlb.top(3); System.out.println(dlb.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}] } }パラメーター:
パラメーター
タイプ
説明
shardKeySize
int
基になるサブリーダーボードの数。デフォルト値は 10 です。この数は動的にスケールアウトできません。サービスの初期段階でこの数を計画してください。
pageSize
int
リーダーボードの各ページのメンバー数。デフォルト値は 10 です。
reverse
boolean
有効な値:
false (デフォルト): 昇順でソートします。
true: 降順でソートします。
useZeroIndexForRank
boolean
有効な値:
true (デフォルト): ランクは 0 から始まります。
false: ランクは 1 から始まります。
詳細については、「alibabacloud-tairjedis-sdk の com.aliyun.tair.tairzset.DistributedLeaderBoard クラス」をご参照ください。
付録: 従来のリーダーボードと分散型リーダーボードの比較
次の表は、従来のリーダーボードと分散型リーダーボードの基本機能の実装を比較したものです。
基本機能 | 従来のリーダーボード | 分散型リーダーボード | ||
実装 | 時間計算量 | 実装 | 時間計算量 | |
メンバーの挿入 | EXZADD を使用して要素を挿入します。 | O(log(N)) |
| O(log(N)) |
メンバーのスコアを更新 | EXZINCRBY を使用してスコアを更新します。 | O(log(N)) |
| O(log(N)) |
メンバーの削除 | EXZREM を使用してメンバーを削除します。 | O(M*log(N)) |
| O(log(N)) |
メンバー数のクエリ | EXZCARD を使用してメンバー数をクエリします。 | O(1) | EXZCARD を使用して各サブキーのメンバー数をクエリし、その結果を合計します。 | O(m) 説明 この列では、m はシャードの数を示します。 |
総ページ数のクエリ | EXZCARD を使用してメンバー数をクエリし、その結果を PAGE_SIZE (ページあたりのレコード数) で割ります。 | O(1) | EXZCARD を使用して各サブキーのメンバー数をクエリし、結果を合計してから、合計を PAGE_SIZE (ページあたりのレコード数) で割ります。 | O(m) |
スコア範囲内のメンバーの総数 | EXZCOUNT を使用してクエリします。 | O(log(N)) | 各サブキーで EXZCOUNT を実行し、結果をマージします。 | m × O(log(N)) |
スコア範囲内のメンバーを削除 | EXZREMRANGEBYSCORE を使用してメンバーを削除します。 | O(log(N)+M) | 各サブキーで EXZREMRANGEBYSCORE を実行します。 | m × O(log(N)) |
メンバーのスコアを取得 | EXZSCORE を使用してクエリします。 | O(1) |
| O(1) |
メンバーのランクを取得 | EXZRANK を使用してクエリします。 | O(log(N)) | 各サブキーで EXZRANKBYSCORE を呼び出し、その結果を合計します。 | m × O(log(N)) |
メンバーのスコアとランクを同時に取得 | EXZSCORE と EXZRANK を使用してクエリします。 | O(log(N)) |
| m × O(log(N)) |
上位 i 番目のメンバーをクエリ | EXZRANGE を使用してクエリします。 | O(log(N)+M) | EXZRANGE を使用して各サブキーから上位 i 人のメンバーをクエリし、結果をマージして最終的な上位 i 人のメンバーを見つけます。 | m × O(log(N)) |
リーダーボードの i ページ目を取得 | EXZRANGE を使用してクエリします。 | O(log(N)) | 各サブキーからターゲットページより前のすべてのメンバーを取得し、それらをソートして最終ページを取得します。 | m × O(log(N)) |
有効期限の設定 | EXPIRE を使用して時間を設定します。 | O(1) | 各サブキーに有効期限を設定します。 | O(m) |
リーダーボードの削除 | DEL を使用して削除します。 | O(N) | 各サブキーを削除します。 | m × O(N) |