一个简单的基于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); } }); } }
测试结果: