• [Java复习] 分布式锁 Zookeeper Redis


    一般实现分布式锁都有哪些方式?

    使用 Redis 如何设计分布式锁?使用 Zookeeper 来设计分布式锁可以吗?

    这两种分布式锁的实现方式哪种效率比较高?

    1. Zookeeper 都有哪些使用场景?

    四大场景:

    • 分布式协调
    • 分布式锁
    • 元数据/配置信息管理
    • HA高可用性

    分布式协调:

      场景:A系统发请求到MQ,B系统消费之后,A系统怎么知道B系统的处理结果?

      解决方案:用Zookeeper实现分布式系统之间协调工作。

       A系统发请求之后,在Zookeeper上对某个节点的值注册监听器,一旦B系统处理完值后就修改Zookeeper的节点值,A系统就立马收到通知。

    ZK分布式锁:

       场景:对某一个数据需要2个修改操作,两台机器同时收到请求,但需要一台执行后另一台才能执行。

       解决方案:使用ZK分布式锁。机器A收到请求后,在ZK创建一个znode,接着执行操作;

       另外一个机器B也尝试创建znode,发现创建不了,注册这个锁的监听器,只能等待机器A执行完成之后再执行。

       ZK 发现机器A释放锁后,ZK会通知机器B, 这样B可以获取锁。

     ZK的实现: 

       zookeeper.create(path…)尝试创建临时节点,创建成功就获取锁;

       如果被别的客户端获取了,就注册一个监听器监听这个锁,可以尝试用CountDownLatch await或者别的方式等待,或者不断循环查询,

       如果监听这个节点被释放,就把latch countDown或者把等待release,重新尝试获取锁。

       也可以基于zookeeper的临时顺序节点来实现,不用while true的循环。多人竞争一把锁时,会排队,后面每个排队的都去监听排在自己前面那个人创建的znode。

    元数据/配置信息管理:

     ZK可以作为很多系统的配置信息管理,比如Kafka, Storm,Dubbo。

    HA高可用:

      大数据系统基于ZK开发HA高可用机制,比如Hadoop,HDFS,Yarm。一个进程/服务做主备两个,主挂了立马通过Zookeeper感知切换到备用进程或服务。

    Redis分布式锁:

        官方叫RedLock,Redis官方支持的分布式锁算法。

       分布式锁3个重要考察点:

    • 互斥
    • 不能死锁
    • 容错

    1. 普通的加锁方式(setnx)

    SET Key(orderId:1lock) Value(随机值) NX PX 30000

      NX:表示只有 key 不存在的时候才会设置成功。(如果此时 redis 中存在这个 key,那么设置失败,返回 nil)

      PX 30000:意思是 30s 后锁自动释放。别人创建的时候如果发现已经有了就不能加锁了。

       

      释放锁就是删除 key ,但是一般可以用 lua 脚本删除,判断 value 一样才删除:

      删除锁的时候,找到 key 对应的 value,跟自己传过去的 value 做比较,如果是一样的才删除。

    if redis.call("get",KEYS[1]) == ARGV[1] then
        return redis.call("del",KEYS[1])
    else
        return 0
    end

      为什么要用这种方式来删除?

      比如A获取锁后,阻塞时间超过30s,锁自动释放了。

      B已经获取锁了,要是这个时候直接删除Key(已经是别人加的锁)的话就会出现问题,所有加随机值加上lua脚本(原子操作)来释放锁。

      这个方案有单点故障风险。如果redis普通主从,如果主从异步复制,主节点挂了, key失效,key还没有同步到从节点,这时候从节点切换为主节点,

      其他人就可以set key,从而拿到锁,分布式锁机制失效。

    2. RedLock算法

      场景:有redis cluster,5个实例。对集群上锁,在大多数节点上锁成功,就算成功。

      上锁步骤:

       获取时间戳,轮流在每个主节点上锁,过期时间较短,比如5个节点,要求3个节点(n/2 + 1); 创建锁的时间小于超时时间,表示创建成功;

       要是锁创建失败,就依次删除之前建立的锁。

       PS:实现比较复杂,在国外还有争议,算法的健壮性可疑。

    Redis 分布式锁和ZK 分布式锁的对比

    • redis 分布式锁,其实需要自己不断去尝试获取锁,比较消耗性能。RedLock算法还不完善。
    • zk 分布式锁,获取不到锁,注册监听器即可,不需要不断主动尝试获取锁,性能开销较小。

    总结,zk 的分布式锁比 redis 的分布式锁牢靠、而且模型简单易用。

    参考资料:

      《互联网Java进阶面试训练营》的笔记 -- 中华石杉

  • 相关阅读:
    P3396 哈希冲突 分块
    大数据之路week01--自学之面向对象java(static,this指针(初稿))
    大数据之路week01--自学之集合_2(列表迭代器 ListIterator)
    大数据之路week01--自学之集合_2(List)
    大数据之路week01--自学之集合_2(Iterator迭代器)
    大数据之路week01--自学之集合_1(Collection)
    大数据之路day05_1--初识类、对象
    大数据之路day04_2--经典bug(equals与==比较不同,break的跳出不同)
    大数据之路day04_1--数组 and for循环进阶
    eclipse断点的使用---for循环举例
  • 原文地址:https://www.cnblogs.com/fyql/p/11981539.html
Copyright © 2020-2023  润新知