Redis分布式锁

分布式系统中,传统的并发控制锁策略不再适用,需要借助分布式锁来控制资源访问。本文介绍了基于数据库、缓存(如Redis)和Zookeeper实现分布式锁的方法,并详细阐述了使用Redis实现分布式锁的步骤,包括设置过期时间、续命机制以及防止锁误删的解决方案,如使用Lua脚本确保原子操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

随着业务发展的需要,原单体单机部署的系统被演化成分布式集群系统后,由于分布式系统多线程、多进程且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的Java API并不能提供分布式锁的能力,为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问,这就是分布式锁要解决的问题。
分布式锁主流的实现方案

  1. 基于数据库实现分布式锁
  2. 基于缓存(redis等)
  3. 基于zookeeper
    解决方案:使用redis实现分布式锁
    set key value NX PX 有效期(毫秒)
    set sku:1:info “ok” NX PX 10000
    表示当 sku:1:info 不存在的时候,设置值为ok,且有效期为1万毫秒
    在这里插入图片描述
    (2)为什么要设置过期时间?
    客户端获取锁后,由于系统问题,如系统宕机了,会导致锁无法释放,其他客户端就无法或锁了,所以需要给锁指定一个使用期限。
    (3)如果设置的有效期太短怎么办?
    比如有效期设置了10秒,但是10秒不够业务方使用,这种情况客户端需要实现续命的功能,可以解决这个问题。
    (4)解决锁误删的问题
    锁存在误删的情况:所谓误删就是自己把别人持有的锁给删掉了。
    比如线程A获取锁的时候,设置的有效期是10秒,但是执行业务的时候,A程序突然卡主了超过了10秒,此时这个锁就可能被其他线程拿到,比如被线程B拿到了,然后A从卡顿中恢复了,继续执行业务,业务执行完毕之后,去执行了释放锁的操作,此时A会执行del命令,此时就出现了锁的误删,导致的结果就是把B持有的锁给释放了,然后其他线程又会获取这个锁,挺严重的。
    如何解决呢?
    获取锁的之前,生成一个全局唯一id,将这个id也丢到key对应的value中,释放锁之前,从redis中将这个id拿出来和本地的比较一下,看看是不是自己的id,如果是的再执行del释放锁的操作。
    (5)还是存在误删的可能(原子操作问题)
    刚才上面说了,del之前,会先从redis中读取id,然后和本地id对比一下,如果一致,则执行删除,伪代码如下
    step1:判断 redis.get(“key”).id==本地id 是否相当,如果是则执行step2 step2:del key;
    此时如果执行step2的时候系统卡主了,比如卡主了10秒,然后redis才收到,这个期间锁可能又被其他线程获取了,此时又发生了误删的操作。
    这个问题的根本原因是:判断和删除这2个步骤对redis来说不是原子操作导致的,怎么解决呢?
    需要使用Lua脚本来解决。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值