• redlock分布式锁真的安全吗


    此文是对http://zhangtielei.com/posts/blog-redlock-reasoning-part2.html文章的个人归纳,如有问题请联系删除

    什么是redlock

    redlock是redis给出的分布式锁的实现规范

    先说说基于单节点redis实现的分布式锁

    SET resource_name random_value NX PX 30000 如果执行成功说明获取到锁了

    random_value需要设置一个唯一标识避免冲突

    resource_name 只有不存在的时候才能set成功 代表获取到了锁

    px 30000 代表过期时间30秒

    需要注意的是

    1. 过期时间必须得设置 避免锁不能释放的情况

    2. random_value还是很有必要的必须不重复 确保锁只能被锁的持有者删除

      举例:

      A获取锁 执行超过px时间 锁被释放

      B获取锁成功 执行

      A执行完释放锁 这时B是没有锁保护的

    3. 释放锁必须要用lua脚本保证原子性

    4. 在主从的情况下,A在master获取到锁 如果master宕机 并且 key还未同步到slave B从slave也可以获取到锁

    由于第4点 单节点redis无法解决这个问题,所以才有了redlock

    redlock算法获取锁的步骤

    1. 记录当前时间

    2. 按顺序依次向客户端申请锁,跟单节点申请锁一样只是多了一个超时时间用于redis节点不可用的情况(几十毫秒级别),获取锁失败立即向下一个客户端申请锁

    3. 当前时间减去第一步获取的时间,如果n/2+1的节点获取锁成功,并且消耗时间未超过锁的有效时间,获取锁成功否则失败

    4.重新计算锁的有效时间,有效时间减去第三步算出来的时间

    5. 如果失败则向所有的redis节点发送lua删除锁操作 (避免redis加锁成功但是客户端未受到消息的情况)

    虽然避免了failover但是 节点崩溃重启的时候仍然有安全性问题

    1. A客户端锁住了 123节点 45没锁住

    2. 此时3节点崩溃但是A客户端在上面加的锁未持久化

    3. 3节点重启 B客户端锁住了 345 获取锁成功

    解决方法有:

    1. 延迟重启,节点崩溃了不立即重启,而是等到超过锁的失效时间之后再重启

    依赖系统时钟导致的不安全性

    1. A客户端在123节点获取锁成功

    2.3节点时钟发生向前跳跃只是3节点上的锁过期

    3.B客户端获取了345节点的锁

    gc pause导致的不安全性

    1. A客户端在接收到12345节点的成功获取锁之前 进行了gc pause超过了锁的有效时间

    2. B客户端获取了123节点的锁

    3. A节点恢复过来之后 拿到了成功的结果 认为自己获取锁成功了

    注意:这个是在获取到成功信息之前 锁就过期了,以前是客户端获取到成功信息之后 锁才过期,破坏了锁服务本身的安全性 这个是不成立的对于redlock 因为redlock有一步是检查获取锁的时间是否超过锁的有效时间

    zookeeper实现分布式锁

    zookeeper的比redis功能多的地方是

    创建/node之后 如果客户端长时间不能应答心跳 zookeeper会删除这个失联客户端创建的所有node节点 不用想redis一样考虑如何设置锁的过期时间

    如果锁被A客户端持有,B客户端来申请锁失败,这时B客户端可以watch这个/node 当node锁被释放的时候 通知客户端B去获取锁 实现阻塞等待的功能

  • 相关阅读:
    06软件构架实践阅读笔记之六
    05软件构架实践阅读笔记之五
    04软件构架实践阅读笔记之四
    03软件构架实践阅读笔记之三
    02软件构架实践阅读笔记之二
    01软件构架实践阅读笔记之一
    实训第四天
    实训第三天
    实训第二天
    实训第一天
  • 原文地址:https://www.cnblogs.com/isnotnull/p/14041374.html
Copyright © 2020-2023  润新知