怎么用Redis配置高可用库存,避免卖断货的那些事儿
- 问答
- 2026-01-17 09:38:33
- 2
怎么用Redis配置高可用库存,避免卖断货的那些事儿
(引用来源:主要基于电商领域常见的库存扣减场景和技术社区如CSDN、InfoQ上关于Redis分布式锁和原子操作的讨论,以及《Redis设计与实现》一书中对相关命令的说明)
咱们今天就来聊聊,在一个电商网站里,怎么用Redis这个速度快得像闪电的内存数据库,来管好商品的库存,确保在大伙儿一窝蜂抢购的时候,既不超卖(就是库存只剩10件却卖出去20件),也不卖断货(系统出错把有货的商品给禁售了),而且整个系统还得结实耐用,就算某台机器突然罢工了,库存数据也不能丢。
最核心的问题就是“超卖”,想象一下,一个热门商品,比如最新款手机,库存就1000台,结果十几万人同时点击购买,如果用普通的编程思路,先查一下库存还剩多少,如果大于零就让你下单,然后去数据库里把库存减1,这在人少的时候没问题,但在高并发下,麻烦就来了,很可能1000个库存,第一万个请求和第一万零一个请求在同一瞬间去查,都看到库存是1,都以为自己能买,然后都去执行减1操作,结果库存变成了负数,这就超卖了,相当于仓库里明明没货了,系统却多确认了好多订单,商家要么发不出货被投诉,要么只能自己亏本采购来赔。
那Redis怎么解决这个难题呢?关键就在于它提供的原子操作,原子操作的意思就是这个操作是“不可分割”的,像一颗原子一样,在执行过程中不会被别的请求打断,Redis有几个命令天生就是原子性的,非常适合用来扣库存。
最常用的一个命令是DECR或者DECRBY。(引用来源:Redis官方文档对DECR命令的定义)它的用法很简单,你事先把商品的库存数量,比如1000,设置到Redis的一个键里,比如stock:product_123,当用户下单时,不是先去查再计算,而是直接对stock:product_123执行DECR命令(每次减1)或者DECRBY stock:product_123 5(一次减5件),这个命令的执行过程是:读取当前值、减去指定数量、写回新值,这三个步骤在Redis内部是一气呵成的,不会有其他命令插队,执行完后,它会返回减完之后的新库存值,你的程序只需要判断这个返回值,如果它大于等于0,说明扣减成功,允许下单;如果它变成了负数,说明库存不足,这次扣减就失败了,不让下单,因为命令是原子的,所以绝对不会出现两个请求同时读到同一个值然后都扣减成功的情况,从根源上杜绝了超卖。
只用DECR有一个小缺点:它允许库存被扣成负数,有时候我们希望库存到0就彻底打住,一点都不能超,这时候可以用另一个组合拳命令:LUA脚本。(引用来源:Redis官方文档中关于LUA脚本原子性的说明)你可以写一小段LUA脚本,大概逻辑是:“先获取当前库存,如果库存大于0,我就减1,并返回成功;否则,直接返回失败”,Redis会保证整个LUA脚本在执行时是原子性的,就像单个命令一样,这样就能实现“库存扣减且不超卖”的精准控制。
好了,超卖问题解决了,但光解决这个还不够,我们还得让库存服务“高可用”,高可用说白了就是“一直能干活儿,偶尔生个小病也能很快恢复”,如果只用一台Redis服务器,万一这台机器硬盘坏了、断电了或者网络断了,那整个网站的库存功能就瘫痪了,这肯定不行。
我们需要搭建Redis集群,通常是主从模式。(引用来源:常见的高可用架构实践,如Redis Sentinel哨兵模式)简单说,就是准备多台Redis服务器,其中一台是“主”,负责处理所有的写操作(比如扣减库存DECR命令);另外几台是“从”,它们实时地从“主”那里复制数据,这样做好处多多:
- 数据备份:即使主服务器突然宕机了,从服务器上还有一份完整的数据副本,库存数据不会丢失。
- 故障转移:我们可以再部署一个叫“哨兵”的监控程序,它时刻盯着主服务器是否健康,一旦发现主服务器宕机,哨兵会自动从剩下的从服务器中选举出一个新的主服务器,让它们顶上去继续提供服务,这个过程是自动的,对于正在抢购的用户来说,可能只是感觉稍微卡顿了一下,很快就恢复了,不会出现长时间的服务中断。
- 分担读压力:像查询库存余量这种读操作,可以直接让从服务器来处理,减轻主服务器的负担。
主从模式也有个细节要注意:数据复制有微小的延迟。(引用来源:对Redis主从复制原理的普遍认知)当主服务器扣减库存后,这个命令传到从服务器并执行,需要一点点时间(通常是毫秒级),如果在数据还没完全同步过去的时候,用户查询库存,查询请求正好落在了数据稍旧的从服务器上,那他看到的库存可能就不是最新的,对于秒杀场景,这可能影响不大,因为核心是扣减的原子性,但如果对实时性要求极高,可以考虑让用户查询关键库存时也走主服务器,或者使用Redis集群的其他高级模式。
除了主从,还有一种更高级的集群方式,能将数据分片存储在多个主节点上,进一步扩展性能和容量,但原理也更复杂一些。
还有一个保障措施是持久化。(引用来源:《Redis持久化》相关技术文章)Redis虽然把数据放在内存里速度快,但万一全体服务器都断电,内存里的数据就全没了,所以需要定期把内存中的数据 snapshot 快照保存到硬盘上(RDB),或者把所有写命令记录到日志文件里(AOF),这样即使完全重启,也能从硬盘上恢复数据,结合主从复制和持久化,库存数据的可靠性就非常高了。
用Redis配置高可用的库存系统,核心三板斧是:第一,用DECR等原子操作或LUA脚本坚决避免超卖;第二,用主从复制加哨兵机制,保证一台机器宕机了还有备份机器能立刻顶上,服务不中断;第三,用持久化功能,防止极端情况下的数据丢失,把这几点做好了,就能搭建一个既能承受巨大抢购流量,又稳定可靠的库存系统了。

本文由钊智敏于2026-01-17发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://www.haoid.cn/wenda/82334.html
