avatar1 avatar
@{[{user.name}]}
希腊·圣域
since February 1500

Zookeeper分布式协调系统 搭建一个简易集群

废话少说,zookeeper主要用于统一的命名状态同步集群管理分布式应用分布式锁等的管理工作。

1. Zookeeper最主要的工作原理概述

真实环境中Zookeeper一般会建立多个节点(node), 这些节点互相联通并进行选举,之后回选举出一个master主节点(或leader节点)和若干followers子节点,选举机制依赖于节点的投票机制,基本过程为:其中一个节点发现master尚不存在(原master死亡/尚未进行第一次选举),则该节点向其他所有节点发送我要想成为master的消息并等待其他节点的相应,如果超过半数或以上的节点同意则该节点随机成为master节点。

基于上面的解释,zookeeper集群中一般会建立>=3的单数个节点来方便master/leader的选举,例如3,5,7个节点这样。

当然实际的选举过程和策略远比这个要复杂的多,并且要处理各种各样不同的情形,还有一个典型的问题:假设有一组zookeeper的集群,当集群中的某些节点组A跟其他节点组B由于网络原因无法通信,但是这A组中的节点可以互相通信,B组中的节点也可以互相通信,这样就造成了会在两个组中同时存在两个leader,当网络恢复时,zookeeper是如何处理的?

2. 为什么要选举出master/leader节点呢

简单来讲,master的作用就是要统领其他节点的更新,因为zookeeper是一个分布式的协调系统,这样需要保证在zookeeper上的任何一个节点所读取到的值必须都是相同的。

Zookeeper是如何更新消息的
当你向其中一个节点发送更新请求时,该节点首先会将请求发送到master,之后master就会向全部子几点发送更新请求并等待反馈,当超过半数的节点反馈更新成功后master会更新自身状态为已更新,所以zookeeper并不能保证每次读取的一致性,由于master会总是存有最新的状态,所以其他所有节点则必须保持跟master的同步状态来同步自己的数据。

3. 模拟zookeeper的使用

  1. 首先下载zookeeper.

  2. 解压后复制三个副本来充当三个不同的节点

  3. 在每一个副本下创建data文件夹来存储信息。

  4. data文件夹下创建文件myid来指明该节点的id号,id号要唯一,该号码信息会在第5步写入配置文件。

  5. 为每一副本修改配置文件,conf/zoo.cfg
    Zookeeper-1


     tickTime=2000
     initLimit=10
     syncLimit=5
     dataDir=/Users/neeson/XPlan/ZooKeeper/zookeeper-1/data //数据存储的地方
     clientPort=2181 //客户端要连接该node所使用的端口
     server.1=localhost:2881:3881 //node互相之间需要通信的端口信息
     server.2=localhost:2882:3882 
     server.3=localhost:2883:3883
    

    Zookeeper-2


     tickTime=2000
     initLimit=10
     syncLimit=5
     dataDir=/Users/neeson/XPlan/ZooKeeper/zookeeper-1/data //数据存储的地方
     clientPort=2182 //客户端要连接该node所使用的端口
     server.1=localhost:2881:3881 //node互相之间需要通信的端口信息
     server.2=localhost:2882:3882 
     server.3=localhost:2883:3883
    

    Zookeeper-3


     tickTime=2000
     initLimit=10
     syncLimit=5
     dataDir=/Users/neeson/XPlan/ZooKeeper/zookeeper-1/data //数据存储的地方
     clientPort=2183 //客户端要连接该node所使用的端口
     server.1=localhost:2881:3881 //node互相之间需要通信的端口信息
     server.2=localhost:2882:3882 
     server.3=localhost:2883:3883
    

  6. 在三个副本的根目录创建两个bash文件来启动和关闭zookeeper集群,如图:



  7. startCluster.shstopCluster.sh

        #!/bin/sh
        echo "Starting keeper 1..."
        echo "`zookeeper-1/bin/zkServer.sh start`"
        sleep 0.5
        echo "Starting keeper 2..."
        echo "`zookeeper-2/bin/zkServer.sh start`"
        sleep 0.5
        echo "Starting keeper 3..."
        echo "`zookeeper-3/bin/zkServer.sh start`"
        echo "Keeper 1, 2, 3 have been started"
    
        #!/bin/sh
        echo "Stopping keeper 1..."
        echo "`zookeeper-1/bin/zkServer.sh stop`"
        sleep 0.5
        echo "Stopping keeper 2..."
        echo "`zookeeper-2/bin/zkServer.sh stop`"
        sleep 0.5
        echo "Stopping keeper 3..."
        echo "`zookeeper-3/bin/zkServer.sh stop`"
        echo "Keeper 1, 2, 3 have been stopped"
    
  8. 运行startCluster.sh后zookeeper的集群就启动完毕,此后切到任意一个节点中运行bin/zkCli.sh来启动zookeeper的命令行工具,它会自动连接当前的节点实例。之后可以通过命令 create /myNode 'Hello' 来创建存储信息,创建完毕后会集群会自动同步消息,此事通过ctrl + c退出当前节点的连接,切入另一个节点并用同样的方式连接zkCli,运行get /myNode来验证信息是否完成同步。

  9. 至此简易的zookeepr的集群架设就已经完成并测试通过了,真正使用集群的时候可以按照群组的返回式进行连接,比如 我现在有A,B,C三个节点,我连接是可以选择同同时输入两个或三个节点的信息,这样就可以保证在启动一个节点宕机后还可以继续读取和写入数据,保证了系统的高可用性。

4. 总结

Zookeeper做一个集群的协调中间件并不适合存储大量数据,当然你可以通过zookeeper的watcher机制来转发消息或通知来达到massage broker的目的,但是实际使用的时候是不推荐这样做的,zookeeper更适合存储和同步少量的元信息(meta),比如配置文件信息,分布式服务的锁等等。关于分布式的锁下面需要用单独的一篇来记录一下,此处暂且略过,它是zookeeper的重要应用之一必须要搞清楚的。

Zookeepr既然不适合做massage broker,我们就需要用另一个消息中间件加zookeeper的配置来做消息中间件 即 - Kafka, Kafka会单独一篇进行记录。