This topic describes how to manage event push notifications in game operations by using Bloom filters to prevent repetitive notifications to players. This topic also describes how to connect to a Tair (Enterprise Edition) instance and perform operations on Bloom filters by using Jedis.
Background information
In modern game operations, game developers and operations teams often launch various events to boost user popularity, engagement, or payment rates. In most cases, events are pushed to players by means of pop-up windows, in-game messages, and non-player character (NPC) tasks. In a complex game environment, developers need to ensure system efficiency while controlling the frequency of pushing event notifications to prevent the user experience from being degraded due to repetitive notifications.
In this scenario, the Bloom filter data structure provides an efficient solution to control repetitive pop-up notifications. A Bloom filter is a probabilistic data structure that is used to determine whether an element is a member of a set. A Bloom filter quickly determines and returns whether an element is possibly in a set or definitely not in a set. The Bloom filter offers low space complexity and fast query, which is suitable for large datasets. However, false positives may also be produced. As a result, a user could miss a notification.
In this scenario, Bloom filters outperform other data structures in the following aspects:
High efficiency: Bloom filters use bit arrays to store large amounts of user data.
Low memory usage: Compared with traditional data structures, Bloom filters use significantly less space, especially when storing the push status of millions of players.
Scalability: Bloom filters are scalable and well-suited for large-scale distributed environments, such as Redis clusters.
The Bloom filter provided by Tair (Enterprise Edition) is compatible with the Redis Bloom filter and is used in the same manner.
Overview
The following section provides sample code on how to use a Bloom filter to manage game event push notifications.
Connect to a Tair (Enterprise Edition) instance.
Create a Bloom filter named
activity_popup
by using thecreateBloom
function in the sample code.In this example, the Bloom filter is expected to store 50,000 elements and has a false positive rate of 1%.
When a player logs in, you can push a notification to the player by using the
handlePopup
function in the sample code.Before you do so, you must check whether a push is required by using the
shouldShowPopup
function in the sample code.If the player ID is not found in the Bloom filter, no notification has been pushed to the player. In this case, you must push a notification to the player and update the push status of the player by using the
updatePopupState
function.If the player ID already exists in the Bloom filter, the player may have received a notification. In this case, do not push the notification again.
Sample code
The following information describes the Jedis dependency:
Sample code:
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);
}
}
Sample success output:
Push a notification to player123.
A notification has been pushed to player123.