このトピックでは、Bloomフィルターを使用してゲーム操作でイベントプッシュ通知を管理し、プレイヤーへの繰り返し通知を防ぐ方法について説明します。 このトピックでは、Jedisを使用してTair (Enterprise Edition) インスタンスに接続し、Bloomフィルターで操作を実行する方法についても説明します。
背景情報
現代のゲーム運用では、ゲーム開発者や運用チームは、ユーザーの人気、エンゲージメント、支払い率を高めるためにさまざまなイベントを開始することがよくあります。 ほとんどの場合、イベントは、ポップアップウィンドウ、ゲーム内メッセージ、および非プレイヤーキャラクター (NPC) タスクによってプレイヤーにプッシュされます。 複雑なゲーム環境では、開発者は、繰り返し通知によるユーザーエクスペリエンスの低下を防ぐために、イベント通知をプッシュする頻度を制御しながら、システム効率を確保する必要があります。
このシナリオでは、ブルームフィルタデータ構造は、繰り返しポップアップ通知を制御するための効率的なソリューションを提供します。 ブルームフィルタは、要素がセットのメンバーであるかどうかを判断するために使用される確率的データ構造です。 ブルームフィルタは、要素が集合内にある可能性があるか、または集合内に全くないかを迅速に判定し、返す。 Bloomフィルターは、スペースの複雑さが低く、クエリが高速で、大規模なデータセットに適しています。 しかしながら、偽陽性が生じることもある。 その結果、ユーザは通知を見逃す可能性がある。
このシナリオでは、次の点でBloomフィルターが他のデータ構造よりも優れています。
高効率: ブルームフィルタはビット配列を使用して大量のユーザーデータを保存します。
低メモリ使用量: 従来のデータ構造と比較して、Bloomフィルターは、特に数百万人のプレーヤーのプッシュステータスを保存する場合、使用するスペースが大幅に少なくなります。
スケーラビリティ: Bloomフィルターはスケーラブルで、Redisクラスターなどの大規模な分散環境に適しています。
Tair (Enterprise Edition) が提供するBloomフィルターは、Redis Bloomフィルターと互換性があり、同じ方法で使用されます。
概要
次のセクションでは、Bloomフィルターを使用してゲームイベントプッシュ通知を管理する方法のサンプルコードを示します。
Tair (Enterprise Edition) インスタンスに接続します。
サンプルコードの
createBloom
関数を使用して、activity_popup
という名前のBloomフィルターを作成します。この例では、ブルームフィルタは、50,000の要素を格納することが期待され、1% の偽陽性率を有する。
プレイヤーがログインすると、サンプルコードの
handlePopup
関数を使用してプレイヤーに通知をプッシュできます。その前に、サンプルコードの
shouldShowPopup
関数を使用してプッシュが必要かどうかを確認する必要があります。プレイヤーIDがブルームフィルタに見つからない場合、通知はプレイヤーにプッシュされていません。 この場合、プレーヤーに通知をプッシュし、
updatePopupState
関数を使用してプレーヤーのプッシュステータスを更新する必要があります。プレイヤーIDがすでにブルームフィルタに存在する場合、プレイヤーは通知を受信している可能性があります。 この場合、通知を再度プッシュしないでください。
サンプルコード
次の情報は、Jedisの依存関係を示しています。
サンプルコード:
import redis.clients.jedis.*;
import redis.clients.jedis.UnifiedJedis;
public class TairBloomFilterDemo {
static HostAndPort hostAndPort=new HostAndPort("r-bp1y****svonly41srpd.redis.rds.aliyuncs.com", 6379); // You can obtain the endpoint and port number of the instance in the console.
static JedisClientConfig config=DefaultJedisClientConfig.builder().password ("tw:Da***3").build(); // The account password of the instance.
static UnifiedJedis unifiedJedis = new UnifiedJedis(hostAndPort, config);
private static final String BLOOM_KEY = "activity_popup";
/**
* Create a Bloom filter key.
*/
public static void createBloom() {
try {
unifiedJedis.bfReserve(BLOOM_KEY, 0.01, 50000);
} catch (Exception e) {
e.printStackTrace(); // Handle exceptions such as connection timeouts.
}
}
/**
* Check whether a specific player ID already exists in the Bloom filter.
*/
public static boolean shouldShowPopup(String playerId) {
try {
return !unifiedJedis.bfExists(BLOOM_KEY, playerId);
} catch (Exception e) {
e.printStackTrace(); // Handle exceptions such as connection timeouts.
return true;
}
}
/**
* Add the player ID to the bloom filter key.
*/
public static void updatePopupState(String playerId) {
try {
unifiedJedis.bfAdd(BLOOM_KEY, playerId);
} catch (Exception e) {
e.printStackTrace(); // Handle exceptions such as connection timeouts.
}
}
/**
* Push a notification to the specified player ID.
*/
public static void handlePopup(String playerId) {
if (shouldShowPopup(playerId)) {
// Push a notification.
System.out.println("Push a notification to the player: " + playerId);
// Update the push status.
updatePopupState(playerId);
} else {
System.out.println("Player" + playerId + "Pushed");
}
}
public static void main(String[] args) {
createBloom();
// Assume that the player ID is player123.
String playerId = "player123";
// Push a notification in the first call.
handlePopup(playerId);
// Do not push a notification in the second call.
handlePopup(playerId);
}
}
サンプル成功出力:
Push a notification to player123.
A notification has been pushed to player123.