redis分布式锁

1.步骤

# 共享资源
127.0.0.1:6379> set num 10
OK
# 加锁
127.0.0.1:6379> setnx lock 1
(integer) 1
# 修改共享资源
127.0.0.1:6379> incrby num -1
(integer) 9
# 解锁
127.0.0.1:6379> del lock
(integer) 1

2. 原理

  • setnx:只有要设置的key不存在时,我们才添加这个key-value。否则不添加

3. 补充

  • 为了防止加锁后因为一些原因没有释放锁,可以选择给锁设置过期时间。

补充

1. 分布式锁应该具备哪些条件

  1. 在分布式系统环境下,一个方法在同一时间只能被一台机器的一个线程执行
  2. 高可用的获取锁和释放锁
  3. 高性能的获取锁和释放锁、
  4. 具备可重入性
  5. 具备锁失效机制,防止死锁
  6. 具备非阻塞特性,可以在没获取到锁的情况下立即返回获取锁失败

2. 分布式锁的三种实现方式

  • 基于数据库
    • 利用唯一索引,多线程获取锁,同时向数据库插入同一个key(唯一约束),谁插入成功则谁获取锁成功,之后处理完业务在删除该条记录
    • 是否具备可重入:插入时添加附加消息可以实现可重入
    • 没有锁失效机制
    • 不具备阻塞锁特性
    • 数据库比redis慢
  • 基于redis
    • redis有很高的性能
    • redis的命令对分布式锁支持较好
    • 有锁失效机制
  • 基于zookeeper实现

3. zookeeper实现分布式锁

1. 一些概念

  • zookeeper的数据存储结构类似于 目录结构,像一棵树,树由节点组成,节点znode分为四种类型

1.1 持久节点

  • 默认节点类型,创建节点的客户端与zookeeper断开连接后,该节点依旧存在

1.2 持久顺序节点

  • 就是在创建节点时,zookeeper根据创建的时间顺序给该节点名称进行编号

1.3 临时节点

  • 持久节点相反,当创建节点的客户端与zookeeper断开连接后,临时节点会被删除

1.4 临时顺序节点

  • 在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与Zookeeper断开连接后,临时节点会被删除。

2. zookeeper分布式锁原理

2.1 获取锁

  • 客户端1 想要获取锁时,在某个节点下(ParentLock)下创建临时顺序节点Lock1,
  • 之后客户端1就查找ParentLock节点下所有临时节点并按时间排序,然后判断自己锁创建的节点是不是顺序最靠前的,如果是第一个节点,则成功获取锁
  • 如果此时再有客户端2来获取锁,也会在ParentLock节点下创建临时顺序节点Lock2
  • 然后客户端2发现自己加的节点Lock2不是顺序最靠前的,于是客户端2向排序仅比它靠前一位节点Lock1注册Watcher
  • 同理有客户端3也添加临时顺序节点Lock3,向Lock2注册watcher

2.2 释放锁

  • 如果客户端1奔溃,关联的节点Lock1也会自动删除,当然也可以主从删除节点Lock1
  • 此时客户端2会收到通知,然后客户端2尝试再次加锁,从而顺利获取到锁

3. redis与zookeeper做分布式锁的比较

3.1 redis

  • set和del指令性能比较高
  • 但实现复杂,要考虑超时,原子性,误删等情况,没有等待锁队列,只能在客户端处自旋等待,效率低下

3.2 zookeeper

  • 有封装好的框架(redis也有),容易实现,有等待锁的队列,大大提升抢锁的效率
  • 删除和添加节点性能较低

3. zookeeper保证ap还是cp

3.1 zookeeper写入流程

  1. 客户端向zookeeper发送一个写的请求,如果当前server不是leader,则会把请求转发给leader
  2. leader收到后开始发起Proposal到Follower,Follower收到来自Leader的提议后,会返回ack响应
  3. 当leader收到过半的ack响应后,就会发送commit提交数据,然后向客户单返回写入成功
  4. 若有新的Follower加入进来,也会对Leader进行数据同步,从而达到集群数据一致性

3.2 zookeeper读取过程

  1. 客户端向zookeeper发出读请求后,无论请求的是leader还是follower,都会直接返回结果。(这样你可能会读到脏数据
  2. 如果使用sync读取,则会先与leader进行数据同步,这样会读取到最新的数据

3.3 总结

  • 是保证ap还是保证cp,感觉看你怎么操作。
  • 如果你读取过程中,能读到脏数据,那么就是ap
  • 如果你读取过程中,采用sync再读取,保证每次读取最新数据,那么就是cp
  • 其实是基于base理论

3.4 补充

  • zookeeper在leader选举期间,会暂停对外提供服务。需要通过leader来保证数据的一致性

4. redis实现分布式锁原理

4.1 不可重入redis分布式锁

  • 原理
    • 利用setnx的互斥性
    • 利用ex避免死锁
    • 释放锁时判断线程标识
  • 缺点
    • 不可重入
    • 无法重试(阻塞获取)
    • 锁超时失效问题

4.2 可重入的redis分布式锁

  • 原理
    • 利用hash结构,记录线程标识(字段)和重入次数(value)
    • 利用watchDog延续锁时间
    • 利用信号量(发布订阅)控制锁重试等待
  • 缺点
    • 集群环境下redis宕机引起锁失效问题(主节点宕机,从节点还未同步数据)

4.3 redisson的multiLock

  • 原理
    • 多个独立的redis节点,必须在所有节点都获取可重入锁之后,才算获取锁成功。
  • 缺点
    • 运维成本高,实现复杂。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值