zoukankan      html  css  js  c++  java
  • 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去获取锁 实现阻塞等待的功能

  • 相关阅读:
    表模块模式与事务脚本模式的代码编写
    解决方案下显示的网站名称被追加编号的问题解决方法
    应用层代码
    关于CodeReview(java)(转)
    关于事务的几个概念介绍(转)
    关于JVM的ClassLoader(转)
    svn相关
    .subversion
    linux用户与组的管理(命令加入、手动加入、加入组、用户之间的切换)
    回调函数
  • 原文地址:https://www.cnblogs.com/isnotnull/p/14041374.html
Copyright © 2011-2022 走看看