zoukankan      html  css  js  c++  java
  • 分布式锁为什么要选择Zookeeper而不是Redis?

    在分布式的应用中,为了防止单点故障,保障高可用,通常会采用主从结构,当主节点挂掉后,从节点可以代替主节点提供服务。

    Redis通过复制 + sentinel哨兵来实现主从模式。

    Zookeeper通过replicated mode复制模式来实现主从模式。

    单从结构上看,Redis和Zookeeper都是主从架构,那Zookeeper的优势是什么?为什么要选择Zookeeper?难道只是因为Zookeeper是目录结构,Redis是K-V结构吗?

    同步机制的不同

    Redis

    Redis在给从节点同步数据时,正常情况是增量同步,也就是主节点的数据修改语句(DML)会异步的同步给从节点。Redis的数据同步没有保障数据一致性的机制,也就是说,一条DML在主节点执行成功时,不能保障其他从节点成功执行了这条数据,这就会造成一个问题,如果在数据没有同步到从节点时,主节点挂掉,就会产生数据丢失的情况。

    Zookeeper

    Zookeeper使用类paxos算法(zab)来保障数据的一致性。简单的讲,当一个DML语句发送给主节点时,Zookeeper需要保证一半以上的节点接收到数据,才会返回成功。并且当主节点挂掉,从节点重新选举时,同步到最新的数据的节点会有优先选举权。

    举个例子:

    一个4节点Zookeeper(A、B、C、D),A是主节点,当执行一个create语句成功时,至少有3台节点执行成功(一半以上),例如A、C、D成功。此时如果A节点挂了,B、C、D进行选举,由于C、D都执行成功了create语句,B没有执行,C、D的数据更加新,具有优先选举权,再根据名称排序,选择C做为主节点。在整个选举过程中,服务不可用,选举完成后,C节点和A节点数据一致,不会出现丢失的情况。

    分布式锁

    要实现分布式锁,需要满足一些要求:

    1. 只能有一个服务的一个线程能获取锁
    2. 一个持有锁的线程挂掉后,锁应该被释放,用来给其他线程用
    3. 一个持有锁的线程没执行完,锁不能释放
    4. 锁释放后,其他等待者可以继续争抢
    5. 管理锁的主节点(Redis或Zookeeper)挂了,重新选举后,不影响锁的持有情况

    Redis解决方案

    问题1、问题2:使用“SET key value EX seconds NX”语句获取锁并设置过期时间

    问题3:另开一个监控线程,监控主线程执行情况,用来延长过期时间

    问题4:等待线程定时检查锁的持有情况

    问题5:暂无或者解决成本很高,需要自己实现类paxos的算法

    Zookeeper解决方案

    通过创建临时节点可以解决问题1,2,3

    watch机制可以解决问题4,并且相比定时检查,watch可以做到更高实时性

    zookeeper的paxos同步机制保障了节点间数据一致性,即使主节点挂掉,也可以保障数据不丢,可以解决问题5

    对比可以发现:

    Zookeeper的机制可以保证分布式锁实现业务代码简单,成本低。

    Redis如果要解决分布式锁的问题,对于一些复杂的情况,很难解决,成本较高。

  • 相关阅读:
    cesium 学习(七) HeadingPitchRoll
    cesium 学习(六) 坐标转换
    cesium 学习(五) 加载场景模型
    Cesium 学习(一)环境搭建
    Cesium 学习(二)所支持的模型数据类型,以及转换
    cesium 学习(四) Hello World
    Cesium 学习(三)各种资源链接
    【Windows编程】系列第十一篇:多文档界面框架
    【Windows编程】系列第十篇:文本插入符
    【Windows编程】系列第八篇:通用对话框
  • 原文地址:https://www.cnblogs.com/chenkeyu/p/14793627.html
Copyright © 2011-2022 走看看