一篇文章带你搞定分布式锁常见问题

一篇文章带你搞定分布式锁常见问题

分布式锁

基本的分布式锁实现

基于zookeeper,redis
例如基于redis:

1)setnx,设置锁,设置过期时间,保存线程标识

2)释放锁的时候要先判断锁是否为当前线程持有的,需要用lua脚本来保证解锁的原子性

释放错锁的问题

1)拿到锁,判断锁是不是自己的,释放锁,这三步并不具备原子性,所以需要写在lua脚本里

如何实现Redisson可重入锁

由于自己写的锁使用了string的setnx,只要方法1上锁,方法1调用的方法二就没法再上锁,会直接返回false。

为啥?

redisson的可重入锁,使用了hash结构key为lock, field为线程名,value为数字

  • 加锁
    • 方法一加锁后,value=1,方法一调用方法二
    • 方法二加锁,Redisson会判断field是否为同一线程,若是,value++,value为2
    • 同理…
  • 解锁
    • 每个方法执行完毕时依次value–
    • 直到value为0,此时会删除redis的该数据,锁完全释放

如何实现锁的可重试/Redisson实现阻塞锁

redis的发布订阅机制实现 等待,唤醒,获取锁失败的重试机制

  • 获取锁失败不是直接重试or返回,而是订阅一下,然后等待
  • 当获取锁成功的线程释放锁后,会发布一条消息
  • 其他线程得到该消息,就会去重新获取锁,获取失败,则继续等待
  • 但也不是无限等待,超过一定时间,它就不会继续等而是返回false

redis的pub/sub只实现广播机制

业务没执行完成,锁过期了咋办/锁的续约机制

WatchDog机制来实现锁的续期,每隔一段时间,重置锁的超时时间

  • 会创建一个守护线程,当锁快到期但是业务线程没执行完时为锁增加时间
  • 当然也不是无限加,会有个上限

锁的主从一致性问题

redis为了保证高可用,会使用主从架构。

会出现以下问题

  • 获取锁时,往redis主节点setnx。主节点加锁后宕机,没更新到从节点
  • 某个从节点成为主节点后,但是新主节点没有锁信息。此时其他线程还是可以加锁

解决方案:Redisson联锁方案,使用多主or多主多从

redLock红锁

联锁方案还存在问题

  • 所有节点都得上锁,才能获取锁成功。那么某个节点网络原因,就会导致加锁时间长,加锁失败
  • 如果主节点宕机,也会加锁失败

使用redLock,它规定只要半数以上加锁成功,就算加锁成功。并且严格规定了加锁时间,该段时间内加锁失败,直接返回。

缺点:部署要求高,多主部署,不推荐哈

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值