用Redis咋实现余额锁定,感觉这功能挺关键的,聊聊它到底怎么管钱的锁
- 问答
- 2025-12-29 14:19:09
- 4
网购下单,你看到一件商品还剩最后一件库存,价格也合适,赶紧点击了“立即购买”,就在你填写收货地址的这几秒钟里,如果有另外一个人也看到了这件商品,也点击了购买,那这件商品不就卖超了吗?这就相当于你的银行账户里有100块钱,你同时用手机和电脑发起两笔90元的转账,如果系统不做处理,两笔都可能成功,你就“花”了180元,但账户里其实只有100元,这肯定不行,这个“处理”,核心就是“锁定”。
Redis因为速度极快,而且操作都是原子性的(这个术语很简单,意思就是一个操作要么完全成功,要么完全失败,不会卡在中间状态),所以特别适合来做这种“锁”的活儿,它就像一个反应飞速的仓库管理员。
具体怎么实现这个“锁”呢?
最核心的思想就是:在动钱(或者库存)之前,先占个“坑位”。
-
生成锁的钥匙:当你的下单请求到达系统时,系统不会立刻去数据库里扣减余额或库存,它会先做一件事:生成一个唯一的标识符,比如可以用“用户ID_订单ID_时间戳”来组合,确保这把“锁”的钥匙是全世界独一无二的,这是为了防止误删别人的锁,后面会说到。
-
占坑位(加锁):系统会向Redis发出一条命令,大概意思是:“嘿Redis,我要在名叫
lock:user_balance:[用户ID]的这个键上挂一把锁。” 如果这个键当前不存在(也就是坑位是空的),Redis就会成功设置这个键,并把刚才生成的唯一标识符作为值存进去,同时会给这个锁设置一个“过期时间”,比如10秒或30秒。
这一步是关键,设置键值和过期时间必须是一个原子操作,在Redis里,通常用
SET key value NX PX 30000这样的命令。NX表示“只有当这个key不存在时才设置”,这就保证了只有第一个请求能成功占住坑位。PX 30000表示这个key在30000毫秒(30秒)后自动过期删除。为什么必须设过期时间? 这是保险丝,万一你的业务逻辑执行到一半,系统崩溃了,导致忘记释放锁,那么这个锁就会永远存在,用户的余额就被永远锁住,谁也动不了,这叫“死锁”,有了过期时间,就算出了意外,最多锁30秒,之后自动释放,恢复正常。 -
检查是否占坑成功:如果Redis返回成功,恭喜你,你这个请求抢到了“锁”,你现在拥有了在这段时间内操作这个用户余额的独家权利,其他任何请求再来尝试给同一个用户加锁,都会因为
NX参数(key已存在)而失败,对于失败的请求,系统可以直接返回“请求过于频繁,请稍后再试”之类的提示。 -
执行核心业务:抢到锁的请求可以安心地执行后续操作了:检查用户余额是否足够,如果足够,就在数据库里把余额扣掉,生成订单等等,因为此时没有其他请求能干扰你,所以不会出现并发扣款的问题。

-
释放锁(腾出坑位):等所有业务逻辑都执行完毕,订单生成了,钱也扣了,你就需要主动把锁释放掉,好让别人能继续操作,释放锁不是简单地把Redis那个key删掉就行,这里有个坑:你不能把别人的锁给删了,你的业务逻辑执行得比较慢,超过了30秒,Redis已经自动把你的锁过期删除了,这时另一个请求趁虚而入,成功加上了它自己的锁,如果你这时再去执行删除操作,删掉的就是新请求的锁,这就乱套了。
安全的释放锁的方法是:在删除之前,先检查一下这个key里的值,是不是你当初设置的那个唯一标识符,只有“钥匙”对得上,才能删除,在Redis里,这通常用Lua脚本来实现,因为Lua脚本的执行也是原子性的,能确保“检查”和“删除”两个动作连贯执行,中间不会被插队,代码逻辑大概是:“如果Redis.get(lock_key) 等于我的唯一标识符,那么我就执行Redis.del(lock_key);否则,什么也不做。”
聊聊它到底怎么“管钱”的
通过上面这个过程,Redis这个“锁”实际上扮演了一个“并发流量调度员”的角色:
- 串行化:它把可能并发的、对同一份资金的多个操作请求,变成了一个一个排队执行的“串行”操作,就像只有一个窗口的银行,大家必须排队办理,不可能两个人同时从同一个账户里取钱。
- 互斥性:在同一时刻,一份钱(或一个库存)只被一个业务请求所持有,这是保证资金安全的核心。
- 避免超卖和超支:从根本上解决了“一件商品卖多次”或“一笔钱花两次”的问题。
- 性能与安全的平衡:如果所有并发控制都交给数据库的行锁之类的东西,在高并发下数据库压力会巨大,而Redis速度极快,承担“锁”这个轻量级但频繁的操作,把最终的资金落地交给数据库,这是一种典型的分工合作,既保证了安全,又兼顾了性能。
实现一个生产级别可靠的分布式锁还有很多细节要考虑,比如过期时间设置多长合适?业务没执行完锁就过期了怎么办(锁续期)?Redis本身如果是集群模式,如何保证锁的高可用?这些都是更深层次的问题,但最基本、最核心的原理,就是上面这个“占坑-业务-释放”的流程,它用很简单的方式,管住了线上交易中最关键的钱袋子。
本文由度秀梅于2025-12-29发表在笙亿网络策划,如有疑问,请联系我们。
本文链接:http://waw.haoid.cn/wenda/70696.html
