- 如果上司给一个任务,让我们在实现微信抢红包这个功能,我们该怎么做?
* 业务思考,实现方式千百种,不追求方法复制,只追求推导过程的思考总结
* 功能点探索
* 新建红包:在DB、cache各新增一条记录
* 抢红包:请求访问cache,剩余红包个数大于0则可拆开红包
* key:1,value:20 string decr原子减,每次减1 , 而decreby减指定数量N
* 拆红包: 20个红包里面有500块,key:1,value:50000(以分为单位) decreby 548,decreby 1055 ,decreby 2329
* 请求访问cache,剩余红包个数大于0则继续,同时获取可抢红包数与金额 * 计算金额(从1分到剩余平均值2倍之间随机数,如果不是最后一个红包,剩余金额预留最少1分给cas更新失败,最后一位拿红包的人) * cas更新数据库(更新红包计数表记录【剩余红包个数、剩余红包金额】、插入领取记录)
* 查看红包记录:用户进来直接查DB即可
1微信红包数据库表设计
- 红包流水表
() () COMMENT () COMMENT () COMMENT () COMMENT () COMMENT () COMMENT COMMENT CURRENT_TIMESTAMP COMMENT InnoDB AUTO_INCREMENT CHARSETutf8mb4 COMMENT;
- 红包记录表
() () COMMENT () COMMENT () COMMENT () COMMENT () COMMENT COMMENT CURRENT_TIMESTAMP COMMENT InnoDB AUTO_INCREMENT CHARSETutf8mb4 COMMENT;
- 将库表导入数据库
- 通过mybatis generator生成代码
2发红包接口实现
- 发红包功能接口开发
* 新增一条红包记录 * 往mysql里面添加一条红包记录 * 往redis里面添加一条红包数量记录 decr * 往redis里面添加一条红包金额记录 decreby
- 抢红包功能接口开发
* 抢红包功能属于原子减操作 * 当大小小于0时原子减失败
- 当红包个数为0时后面进来的用户全部抢红包失败,并不会进入拆红包环节
- 抢红包功能扩展设计
* 将红包ID的请求放入请求队列中,如果发现超过红包的个数,直接返回 * 类推出token令牌和秒杀设计原理
- 注意点
* 抢到红包不到能拆成功
* 2014年的红包一点开就知道金额,分两次操作,先抢到金额,然后再转账。
2015年后的红包的拆和抢是分离的,需要点两次,因此会出现抢到红包了,但点开后告知红包已经被领完的状况。进入到第一个页面不代表抢到,只表示当时红包还有。
3 抢红包接口实现
- 抢红包功能接口开发
* 在抢红包这里并不能保证用户已经能领到这个红包
- 抢红包只是做了一个判断,判断当前是否还有红包 - 有红包则返回可以领 - 没红包则返回不可以领
- 拆红包功能接口开发
* 拆红包才是用户能领到红包 * 这时候要先减redis里面的金额和红包数量 * 减完金额再入库
4微信红包设计算法分析
- 玩法:微信金额是拆的时候实时算出来,不是预先分配的,采用的是纯内存计算,不需要预算空间存储- 分配: * *发100块钱,总共10个红包,那么平均值是10块钱一个,那么发出来的红包的额度在0.01元~20元之间波动* * 当前面4个红包总共被领了30块钱时,剩下70块钱,总共6个红包,那么这7个红包的额度在:0.01~(70➗6✖️2)=23.33之间波动(红包金额/个数*2) * 这样算下去,可能会超过最开始的全部金额,因此到了最后面如果不够这么算,那么会采取如下算法:保证剩余用户能拿到最低1分钱即可 - 存储:数据库会累加已经领取的个数与金额,插入一条领取记录。入账则是后台异步操作 - 转账:通过财付通往红包所得者账户转账,过程通过是异步操作
抢红包项目总结
- take all操作
- 入库转账时需要保证红包个数和红包剩余金额正确- 高并发处理:红包如何计算被抢完? - cache会抵抗无效请求,将无效的请求过滤掉,实际进入到后台的量不大。cache记录红包个数,原子操作进行个数递减,到0表示被抢光- 性能扩展 * 多主sharding,水平扩展机器 * 数据库层面sharding分片 * redis层面sharding分片技术 - 业务能动性,从发展的角度来看待业务- 观察总结,技术赋能业务
技术之家希望本篇文章对你有用!!
欢迎来到技术之家,
如需转载,烦请保留本文链接和出处:http://www.jszja.com/contents/14/1459.html
您的支持将是我们前进的动力!如对本篇文章有疑问或建议,请通过本站下方邮箱联系我们,让技术之家每天进步一点点!(●'◡'●)