开篇:

之前也看过一些相关的书籍,最近又在学习redis的相关知识,不过这次偏实战一些,花了几天时间做了一个抢红包的功能,把设计的思路以及最终的源码贴出来给大家分享一下,本人自己自测了一下,能非常清楚的支持10000以上的QPS,估计还能支持更高,(特别说明,这里要抛去数据库,因为数据库在插入的时候存在明显瓶颈,本人机器4核8G),压测是利用Jmeter读取脚本的形式进行压测,此次测试,源码,数据库,jmeter压测工具都在本人机器上。

功能设计:

分布式redis实现抢红包 redis抢红包设计_压测

新建红包:并发较小,建议先让数据进入缓存(redis),然后再进行持久化,注意考虑到两个动作的保证同一个事务,redis放入两个key,分别为:{key1:红包总金额},{key2,红包总数}。

抢红包:并发较大,主要操作的是redis,为了最大的发挥效能,本次注意是利用lua脚本进行操作,且能保证原子性。

拆红包:为本次功能的重点,拆红包,涉及到各种校验例如改用户是否已经抢过红包了,红包金额还剩下多少,红包总数还剩下多少,红包金额和红包总数是否能匹配上,特别是在大并发的情况下,如果保证数据的一致性。

表结构设计:

DROP TABLE IF EXISTS `red_packet_info`;
 CREATE TABLE `red_packet_info` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `red_packet_id` bigint(11) NOT NULL DEFAULT '0' COMMENT '红包id,采用timestamp+5位随机数',
   `total_amount` int(11) NOT NULL DEFAULT '0' COMMENT '红包总金额,单位分',
   `total_packet` int(11) NOT NULL DEFAULT '0' COMMENT '红包总个数',
   `remaining_amount` int(11) NOT NULL DEFAULT '0' COMMENT '剩余红包金额,单位分',
   `remaining_packet` int(11) NOT NULL DEFAULT '0' COMMENT '剩余红包个数',
   `uid` int(20) NOT NULL DEFAULT '0' COMMENT '新建红包用户的用户标识',
   `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
   `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8mb4 COMMENT='红包信息表,新建一个红包插\r\n入一条记录';-- ----------------------------
 -- Table structure for red_packet_record
 -- ----------------------------
 DROP TABLE IF EXISTS `red_packet_record`;
 CREATE TABLE `red_packet_record` (
   `id` int(11) NOT NULL AUTO_INCREMENT,
   `amount` int(11) NOT NULL DEFAULT '0' COMMENT '抢到红包的金额',
   `nick_name` varchar(32) NOT NULL DEFAULT '0' COMMENT '抢到红包的用户的用户名',
   `img_url` varchar(255) NOT NULL DEFAULT '0' COMMENT '抢到红包的用户的头像',
   `uid` int(20) NOT NULL DEFAULT '0' COMMENT '抢到红包用户的用户标识',
   `red_packet_id` bigint(11) NOT NULL DEFAULT '0' COMMENT '红包id,采用timestamp+5位随机\r\n数',
   `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '创建时间',
   `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB AUTO_INCREMENT=16448 DEFAULT CHARSET=utf8mb4 COMMENT='抢红包记录表,抢一个红包插\r\n入一条记录';

接口界面

分布式redis实现抢红包 redis抢红包设计_分布式redis实现抢红包_02