设计火爆秒杀系统,聊聊用Redis怎么写高并发代码才靠谱
- 问答
- 2025-12-30 05:32:41
- 2
(引用来源:主要基于常见的互联网高并发架构实践及Redis官方文档中的思路)
要设计一个能扛住火爆秒杀的系统,比如像双十一抢购或者热门演唱会门票开售那种场景,核心就一句话:尽一切可能把压力挡在数据库之前,因为数据库是个老实人,你让它同时处理几万几十万的“减库存”请求,它立马就趴窝了,我们得找个身手敏捷的“门神”,这个角色非Redis莫属。
Redis为什么能当此大任?主要是因为它快,它把数据都放在内存里操作,速度比读写硬盘的数据库快好几个数量级,而且它是单线程处理命令,别看是单线程,它不用考虑锁的竞争,反而避免了多线程的麻烦,简单又高效,那我们怎么用Redis这个神器来写高并发的秒杀代码呢?得一步步来,不能乱来。
第一步:热身准备——先把商品库存“搬”到Redis里
秒杀开始前,我们不能让请求直接去查数据库还有没有货,正确的做法是,在活动开始之前,就把要秒杀的商品和对应的库存数量,提前设置到Redis里,有1000部特价手机,我们就在Redis里存一个键值对,key可以是 seckill:stock:商品ID,value就是库存数量1000。

SET seckill:stock:12345 1000
这样,所有后续的库存查询和扣减操作,都在内存里完成,速度飞快。
第二步:核心战斗——原子性地扣减库存,这是最关键的一步
当海量用户同时点击“立即抢购”时,会同时发出成千上万个“减一”的请求,这里最忌讳的做法是:程序先GET key拿到当前库存(比如是100),判断大于0,然后再SET key为99,这在并发下是灾难性的,因为A和B两个请求可能同时读到库存是100,都认为可以下单,然后都去减1,结果库存只减了一次,变成了99,但却可能被判定成了两个成功订单,这就是超卖。
我们必须用Redis的原子操作,Redis的命令是单线程执行的,一个命令执行时不会被其他命令打断,我们直接用 DECR 或者 DECRBY 命令。

DECR seckill:stock:12345
这个命令会直接将键对应的值减1,并且返回减之后的结果,整个过程是一个不可分割的原子操作,然后我们的代码只需要判断返回值就行了:
- 如果返回值大于等于0,恭喜你,抢购成功,获得了购买资格。
- 如果返回值小于0(比如是-1),说明库存已经扣没了,抢购失败。
就这么简单的一步,利用Redis天生的原子性,完美解决了最令人头疼的库存超卖问题。
第三步:登记造册——把成功抢到的人记下来
光扣减库存还不够,我们得知道是谁抢到了,但这里又有个陷阱:不能抢购成功一个就立刻往数据库里写一条订单记录,瞬间几万的成功请求写入数据库,数据库还是可能扛不住。

我们的策略是:异步化处理,在Redis里扣减库存成功的同时,我们把抢购成功的用户信息(比如用户ID)暂时存到Redis的一个列表(List)或集合(Set)里。
LPUSH seckill:success:12345 用户ID
这个LPUSH操作也很快,这样,我们就完成了一个最核心的同步流程:原子扣库存 + 记录成功用户,这个流程极快,能最大限度地承受高并发冲击。
第四步:善后工作——慢慢消化
后台我们可以启动一个或多个独立的、速度不那么快的 worker( worker可以理解为一个后台处理程序),定时去Redis里取出那些成功抢购的记录(比如用RPOP从列表里取),然后有条不紊地、分批地创建真正的订单,写入数据库,再通知用户付款。
这样,就把瞬间的巨大写压力,变成了一个平滑的、持续的流量,数据库就能轻松处理了。
另外几个必须要注意的“坑”:
- 应对恶意请求:可能有人用脚本疯狂发送请求,即使库存为0了也一直发,这会给系统造成不必要的压力,我们可以在库存减到0后,直接在Redis里设置一个明显的标记,
SET seckill:over:12345 true,后续请求进来,先查这个标记,如果已经是true,直接返回“已售罄”,连DECR操作都省了。 - 缓存穿透:如果有人故意请求一个根本不存在的商品ID,每次都会查到Redis里没有数据,可能就会去查数据库,给数据库压力,解决办法是对不存在的数据也做个短暂缓存(比如缓存一个空值几分钟),避免频繁穿透到数据库。
- Redis本身别成瓶颈:虽然Redis很强,但它的网络带宽和处理能力也有上限,对于极端热门的秒杀,可以考虑对商品库存进行分片,比如10000件商品,分成10个键来存,每个键存1000件库存,
seckill:stock:12345:01到seckill:stock:12345:10,这样请求可以分散到不同的Redis键上,压力也就分散了。 - 保证Redis高可用:这么重要的“门神”可不能宕机,一定要用Redis的主从复制、哨兵或者集群模式,确保即使一台Redis机器挂了,还有备用的能立刻顶上去。
用Redis写高并发秒杀代码的靠谱思路就是:前置库存到Redis → 利用原子操作(如DECR)解决超卖 → 异步记录结果并后续处理 → 加上各种防护措施(防超卖、防穿透、限流等),核心思想是“快慢分离,异步化解耦”,让专业的工具(Redis)做它最擅长的事(高速读写和原子操作),从而保护系统中最脆弱的部分(数据库),最终平稳度过秒杀洪峰。
本文由歧云亭于2025-12-30发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:https://www.haoid.cn/wenda/71083.html
