一個簡單的基於Redis實現搶紅包功能,分為兩個步驟:
1、拆分紅包
/**
* 拆紅包 1、紅包金額要被全部拆分完 2、紅包金額不能差的太離譜
*
* @param total
* @param count
* @return
*/
public static int[] SplitRedPacket(int total, int count) {
int use = 0;
int[] array = new int[count];
Random random = new Random();
for (int i = 0; i < count; i++) {
if (i == count - 1)
array[i] = total - use;
else {
int avg = (total - use) * 2 / (count - i);// 2 紅包隨機金額浮動系數
array[i] = 1 + random.nextInt(avg - 1);
}
use = use + array[i];
}
return array;
}
2、保存紅包
/**
* 存紅包 采用redis的list結構
*
* @param packetId
* @param packets
*/
public static void SaveRedPacket(String packetId, int[] packets) {
RedisClient redisClient = RedisClient.create("redis://127.0.0.1:6379/0");
StatefulRedisConnection<String, String> connection = redisClient.connect();
RedisCommands<String, String> syncCommands = connection.sync();
for (int packet : packets) {
syncCommands.lpush("Packet:" + packetId, packet + "");
}
connection.close();
redisClient.shutdown();
}
3、搶紅包
/**
* 搶紅包
*
* @param packetId
*/
public static void GrabRedPacket(String packetId) {
RedisClient redisClient = RedisClient.create("redis://127.0.0.1:6379/0");
StatefulRedisConnection<String, String> connection = redisClient.connect();
RedisCommands<String, String> syncCommands = connection.sync();
String res = syncCommands.lpop("Packet:" + packetId);
System.out.println("搶到紅包:" + res);
connection.close();
redisClient.shutdown();
}
最后完整測試demo如下:
public static void main(String[] args) {
final String packetId = UUID.randomUUID().toString();
// 紅包金額(以分為單位,無精度損失問題)
int total = 2000;
// 紅包數量
int count = 7;
// 拆紅包
int[] packets = SplitRedPacket(total, count);
// 存紅包
SaveRedPacket(packetId, packets);
// 搶紅包
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
for (int i = 0; i < 20; i++) {
cachedThreadPool.execute(new Runnable() {
public void run() {
GrabRedPacket(packetId);
}
});
}
}
測試結果:

