Zookeeper

Zookeeper

分布式协调服务

Zookeeper是一个主从集群

存在一个leader主,它可以写操作,其他机器只能读,但是也就存在主单点故障问题

主单点故障问题

会快速(200MS以内)从追随者中重新选举一个新的leader出来。

角色

  1. leader
  2. follower
  3. Observer

    Zookeeper的文件结构

    zookeeper是一个目录树结构
    每个Node都只有1MB的大小

  4. 持久节点

  5. 持久序列节点
  6. 临时节点
    1. 属于当前会话,连接断开,节点被删除
    2. 临时节点无法创建子节点
  7. 临时序列节点

image.png

Zookeeper的保证

ZooKeeper 非常快速且非常简单。但是,由于它的目标是成为构建更复杂服务(例如同步)的基础,因此它提供了一组保证。这些是:
顺序一致性 - 来自客户端的更新将按发送顺序应用。
原子性 - 更新要么成功要么失败。没有部分结果。
单一系统映像 - 无论连接到哪个服务器,客户端都将看到相同的服务列表视图。
可靠性(持久化) - 应用更新后,它将从那时起一直存在,直到客户端覆盖更新。
及时性(最终一致性) - 系统的客户视图保证在特定时间范围内是最新的。

zookeeper

  1. tickTime=2000 每次心跳的毫秒间隔
  2. initLimit=10 最多可以忍追随者10次没有心跳
  3. sysncLimit = 5 leader发送了同步请求最多忍5次心跳的时间没有回复
  4. dataDir=/var/mashibing/zk 持久化目录
  5. clientPort = 2181 服务端口号

    SessionID

    一个客户端连接服务器,会在服务器端生成一个SessionID
    创建的临时节点属于该会话。断开会被删除

    zookeeper命令

  6. create [-s][-e] 创建一个节点,默认是持久节点。-s为序列节点,后面会跟一个序号,-e为临时节点

    节点状态(包含事务ID)

    Zookeeper - 图2
    每个节点下面都会保存事务ID

  7. cZxid:0x180000001e 创建的事务ID

  8. mZxid :0x180000001e 修改的事务ID
  9. pZxid :0x180000001e 子节点最后一次被修改的事务ID

每个create会使得三个ID加一
每个set会使得mZxid加一
新建sessionid和删除也会消耗一个事务ID

需要三个及以上节点

1).zookeeper集群的写操作,由leader节点负责,它会把通知所有节进行写入操作,只有收到半数以上节点的成功反馈,才算成功。如果是部署2个节点的话,那就必须都成功。
2).zookeeper的选举策略也是需要半数以上的节点同意才能当选leader,如果是偶数节点可能导致票数相同的情况
3).只有当半数以上的节点存活时 zookeeper集群才能对外服务,维持正常状态,如果是2个节点,只要其中一个挂掉,那么剩下的1个并不满足半数以上规则。

利用Zookeeper实现分布式锁

因为临时节点session删除也会被删除,所以不会出现因为单点故障出现的死锁
以下为两种实现锁的方式

  1. 临时节点作为锁,监控临时节点是否存在
  2. 序列临时节点作为锁,可以实现队列式的锁。

    安装过程

    安装笔记:
    准备 node01~node04
    1,安装jdk,并设置javahome
    , node01:
    2,下载zookeeper zookeeper.apache.org
    3,tar xf zookeeper.
    .tar.gz
    4,mkdir /opt/mashibing
    5, mv zookeeper /opt/mashibing
    6,vi /etc/profile
    export ZOOKEEPERHOME=/opt/mashibing/zookeeper-3.4.6
    export PATH=_PATH
    :ZOOKEEPER_HOME/bin
    7,cd zookeeper/conf
    8,cp zoo.sem*.cfg zoo.cfg
    9,vi zoo.cfg
    dataDir=
    server.1=node01:2888:3888
    10, mkdir -p /var/mashibing/zk
    11,echo 1 > /var/mashibing/zk/myid
    12,cd /opt && scp -r ./mashibing/ node02:pwd
    13:node02~node04 创建 myid
    14:启动顺序 1,2,3,4
    15:zkServer.sh start-foreground
    zkCli.sh
    help
    ls /
    create /ooxx “”
    create -s /abc/aaa
    create -e /ooxx/xxoo
    create -s -e /ooxx/xoxo
    get /ooxx
    netstat -natp | egrep ‘(2888|3888)’

    ZAB 原子广播协议

    原子:成功、失败。没有中间状态
    广播:分布式多节点,过半通过
    zk的数据状态在内存
    用磁盘保存日志,
    广播的修改命令会先放在log中,leader发现过半之后才会重新发送write内存的操作

    paxos 算法

    选举投票,过半通过
    投票的时候先比较事务xid,再比较id

    zk的watch

    观察者模式
    提供了对某一个节点的监听
    可以把监听器作为回调函数传到watch等到传回事件

    java api

    1. ZooKeeper zk = new
    2. ZooKeeper("192.168.150.11:2181,192.168.150.12:2181,192.168.150.13:2181,192.168.150.14:2181",
    3. String pathName = zk.create("/ooxx", "olddata".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
    4. final Stat stat=new Stat();
    5. byte[] node = zk.getData("/ooxx", new Watcher() {
    6. @Override
    7. public void process(WatchedEvent event) {
    8. System.out.println("getData watch: "+event.toString());
    9. try {
    10. //true default Watch 被重新注册 new zk的那个watch
    11. zk.getData("/ooxx",this ,stat);
    12. } catch (KeeperException e) {
    13. e.printStackTrace();
    14. } catch (InterruptedException e) {
    15. e.printStackTrace();
    16. }
    17. }
    18. }, stat);

    zookeeper实现的分布式锁

    Zookeeper - 图3