分布式锁的实现方式

实现方式

基于数据库实现,基于缓存redis实现,基于zookeeper实现

需要解决的问题

多进程可见:多进程可见是实现分布式锁的基础,redis天然支持

互斥:同一时刻,只能有一个进程可以获取锁,执行任务后释放,

可重入:同一进程再次获取锁不会被死锁

阻塞锁:获取失效时,具备重试机制,尝试再次获取锁

性能好:效率高,应对高并发场景

高可用:避免服务器宕机或者具有处理宕机的处理措施

失效考虑的问题

例如 setnx只有第一次能添加,即互斥,

设置过期时间以及finally中根据key释放锁来解决程序异常或者服务器宕机时的锁释放问题

如果setnx成功后还没来得及设置过期时间怎么办,需要确保setnx和设置过期时间的原子性:set  lock 001 NX EX 100,利用nx和ex命令同时执行来保证原子性,ex 100值设置过期时间为100

A线程获取锁,但是执行过程中程序阻塞导致程序还没有执行完锁超时已被释放,B线程此时拿到了锁刚开始处理业务逻辑,A线程逻辑执行完成来释放锁,就会把B的锁给释放掉,C线程此时进来也可以拿到锁了,就会出现B,C线程安全问题

解决:添加锁时给锁做一个唯一标识,加锁的名字

可重如问题:加锁是记录一下获取到锁的线程是谁,第二次获取时先把线程的名字取出来,如果是已获取到的锁的线程又来获取锁,则直接放行

单锁重入出现嵌套获取锁时,不能在内部就把锁释放,应该在最外层释放,毕竟要记录线程名字时,还要记录锁重入了几成,没释放一次锁记录减一,知道最外层时才能del 锁的key

可以用redis的hash结构,key = lockkey ,value=map('线程名字','重入的层数')

实现以下这些命令的线程安全问题,保证原子性,需要用到LUA脚本,一次性执行。

 

阻塞特性的实现:for循环去获取锁,一次失败等一会再去获取,如果循环到达一定的总时长在抛获取锁失败,或者用更优的方式利用redis的发布订阅机制,释放锁有取发布一条消息,其他线程订阅到消息后在去尝试获取锁

 

高可用:主从同步未完成时,主宕机导致锁丢失,解决有一个redlock算法,多台机器都去获取锁,半数以上获取到才认为是成功获取,即使一台机器挂了还有几台,这样可以解决锁丢失的问题

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值