一個簡單的基於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); } }); } }
測試結果: