高并发系统设计 -- 抢红包设计

抢红包的业务分析

在这里插入图片描述

可以明显的看到打开了红包不一定可以抢到。这样做的好处是:

  • 符合现实生活逻辑,有仪式感
  • 防止误领,发现不对劲可以马上退出
  • 流程拆的长一些,平摊高并发下的压力

在这里插入图片描述

预拆包:我在发红包的时候,就已经把所有的东西都计算好了放在redis里面了。

实时计算:在抢红包的时候进行现场计算。

我选择的时把红包提前拆好,虽然提前拆好需要占用Redis的一些存储,但是这样可以让抢红包的速度到达最快。

发红包

发红包的时候需要一些算法,这里采用的是二倍均值法

二倍均值法可以在正态分布的前提下做到抢红包相对的公平。计算方法如下:

每次抢到的金额 = 随机区间(0, M/N*2)。

在这里插入图片描述

发红包的时候需要指定红包的金额和个数。然后通过二倍均值法计算后放入Redis。这里我们采用的数据结构是List类型,因为List抢走一个红包和红包库存呢减一是一个原子性操作。而且List类型的数据结构就决定了获取库存的时间复杂度是O(1),是可行的。到时候按照顺序弹出即可。

在这里插入图片描述

拆红包

用户点击红包的时候查看库存,如果库存为0的话直接显示红包已经抢完了,并且把详细信息显示。如果还有库存的话,就可以进入抢红包的环节了。

抢红包

用户点击抢红包,此时再次判断库存是否充足,如果充足的话判断用户是否抢过红包,如果两个条件都满足的话,就抢红包成功,从Redis里面弹出一个红包给用户,更新对应的Redis(红包总金额要扣除了),然后使用消息队列异步的调用服务,将用户的金额进行相应的加上。

在这里插入图片描述

与此同时,需要记录哪些用户已经抢过红包了。

在这里插入图片描述

退款

使用延迟队列,24小时后进行消息的消费,如果发现数据库里面还有相应的缓存,那么就需要把剩下的金额退还给用户。具体过程是查看Redis的某个key是否还存在。如果还存在的话那么就把List里面的红包全部弹出,然后把金额归还给用户。然后把红包key删除掉。

高并发场景下可能会遇到的问题

超卖问题

因为查看是否还有库存扣减库(抢红包)存两个操作不是原子性的,因此我们可以使用Redis+Lua实现原子性操作。

Lua实现抢红包的流程:

  • 查询用户是否抢过红包
  • 查询是否还有红包
  • 有的话就扣减红包Redis弹出一个
  • 没有的话就返回

使用 EVAL 命令每次请求都需要传输 Lua 脚本 ,若 Lua 脚本过长,不仅会消耗网络带宽,而且也会对 Redis 的性能造成一定的影响。

思路是先将 Lua 脚本先缓存起来 , 返回给客户端 Lua 脚本的 sha1 摘要。 客户端存储脚本的 sha1 摘要 ,每次请求执行 EVALSHA 命令即可。

img

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡桃姓胡,蝴蝶也姓胡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值