Redis秒杀系统架构设计

导读

  前二天了一篇,Redis高级项目实战(点我直达),SpringBoot整合Redis附源码(点我直达),今天我们来一下Redis秒杀系统的设计。当然啦,Redis基础知识还不过关的先去加强下自身内功,然后在回来看这篇,Redis基础知识(点我直达)。为啥写这个微信抢红包项目呢,公司0202年08月22日,公司周年庆,抢了100多红包🧧,O(∩_∩)O哈哈~

微信抢红包实现原理

业务流程分析

 

功能拆解

新建红包

  在DBRedis分别新增一条记录

抢红包(并发)

  请求Redis红包剩余个数大于0才可以等会0时,提示用户,红包已抢完

拆红包(并发)

用到技术

Redis中数据类型的String特性原子递减DECR key)和减少指定值DECRBY key decrement

业务

  1. 请求Redis,当剩余红包个数大于0红包个数原子递减,随机获取红包
  2. 计算金额,当最后一个红包时,最后一个红包金额=总金额-总已抢红包金额
  3. 更新数据库

查看红包记录

  查询DB即可

数据库表设计

红包流水表

1CREATE TABLE `red_packet_info` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `red_packet_id` bigint(11) NOT NULL DEFAULT 0 COMMENT '红包id,采⽤ 4timestamp+5位随机数', 5 `total_amount` int(11) NOT NULL DEFAULT 0 COMMENT '红包总⾦额,单位分', 6 `total_packet` int(11) NOT NULL DEFAULT 0 COMMENT '红包总个数', 7 `remaining_amount` int(11) NOT NULL DEFAULT 0 COMMENT '剩余红包⾦额,单位 8分', 9 `remaining_packet` int(11) NOT NULL DEFAULT 0 COMMENT '剩余红包个数', 10 `uid` int(20) NOT NULL DEFAULT 0 COMMENT '新建红包⽤户的⽤户标识', 11 `create_time` timestamp COMMENT '创建时间', 12 `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE 13CURRENT_TIMESTAMP COMMENT '更新时间', 14 PRIMARY KEY (`id`) 15) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='红包信息 16表,新建⼀个红包插⼊⼀条记录';

红包记录表

1CREATE TABLE `red_packet_record` ( 2 `id` int(11) NOT NULL AUTO_INCREMENT, 3 `amount` int(11) NOT NULL DEFAULT '0' COMMENT '抢到红包的⾦额', 4 `nick_name` varchar(32) NOT NULL DEFAULT '0' COMMENT '抢到红包的⽤户的⽤户 5名', 6 `img_url` varchar(255) NOT NULL DEFAULT '0' COMMENT '抢到红包的⽤户的头像', 7 `uid` int(20) NOT NULL DEFAULT '0' COMMENT '抢到红包⽤户的⽤户标识', 8 `red_packet_id` bigint(11) NOT NULL DEFAULT '0' COMMENT '红包id,采⽤ 9timestamp+5位随机数', 10 `create_time` timestamp COMMENT '创建时间', 11 `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE 12CURRENT_TIMESTAMP COMMENT '更新时间', 13 PRIMARY KEY (`id`) 14) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='抢红包记 15录表,抢⼀个红包插⼊⼀条记录';

发红包API

发红包接口开发

  • 新增一条红包记录
  • 往mysql里面添加一条红包记录
  • 往redis里面添加一条红包数量记录
  • 往redis里面添加一条红包金额记录

  注意,往db中就单纯存入一条记录,Service层和Mapper层,就简单的一条sql语句,主要是提供思路,下面会附案例源码,不要慌

抢红包API

  • 抢红包功能属于原子减操作
  • 当大小小于0时原子减失败
  • 红包个数为0时,进来的用户全部抢红包失败,并不会进入拆红包环节
  • 抢红包功能设计
    • 将红包ID的请求放入请求队列中,如果发现超过红包的个数,直接返回
  • 注意事项
    • 抢到红包不一定能拆成功

 抢红包算法拆解

  通过上图算法得出靠前面的人,手气最佳几率小手气最佳,往往在后面

  1. 发100元,共10个红包,那么平均值是10元一个,那么发出来的红包金额在0.01~20元之间波动
  2. 当前面4个红包总共被领了30元时,剩下70元,总共6个红包,那么这6个红包的金额在0.01~23.3元之间波动

抢红包接口开发

测试

发红包

模拟高并发抢红包(Jmeter压测工具)

  因为我发了10个红包金额是20000,使用压测工具,模拟50个请求只允许前10个请求能抢到红包并且金额等于20000

项目源码下载

链接: https://pan.baidu.com/s/1knmVMKBldVe46cmXqqfGpw  密码: a7o7

未完待续

  微信上有个小伙伴刚好要做一个秒杀的系统,催我赶紧把博客更新出来。过2天继续往下更新,布隆过滤器。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Redis秒杀系统架构设计 - HelloWorld