zoukankan      html  css  js  c++  java
  • [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进阶面试训练营》的笔记 -- 中华石杉

  • 相关阅读:
    centos 编码问题 编码转换 cd到对应目录 执行 中文解压
    centos 编码问题 编码转换 cd到对应目录 执行 中文解压
    centos 编码问题 编码转换 cd到对应目录 执行 中文解压
    Android MVP 十分钟入门!
    Android MVP 十分钟入门!
    Android MVP 十分钟入门!
    Android MVP 十分钟入门!
    mysql备份及恢复
    mysql备份及恢复
    mysql备份及恢复
  • 原文地址:https://www.cnblogs.com/fyql/p/11981539.html
Copyright © 2011-2022 走看看