本文共 5078 字,大约阅读时间需要 16 分钟。
单机环境下,jdk、zookeeper安装完毕,基于一台虚拟机,进行zookeeper伪集群搭建,zookeeper集群中包含3个节点,节点对外提供服务端口号分别为2181、2182、2183。
1.基于zookeeper-3.4.10复制三份zookeeper安装好的服务器文件,目录名称分别为zookeeper2181、zookeeper2182、zookeeper2183
cp -r zookeeper-3.4.10 zookeeper2181cp -r zookeeper-3.4.10 zookeeper2182cp -r zookeeper-3.4.10 zookeeper2183
2.修改zookeeper2181服务器对应配置文件
#服务器对应端口号clientPort=2181#数据快照文件所在路径dataDir=/opt/zookeeper2181/data#集群配置信息#server.A=B:C:D #A:是一个数字,表示这个是服务器的编号 #B:是这个服务器的ip地址 #C:Zookeeper服务器之间的通信端口 #D:Leader选举的端口 server.1=172.16.114.135:2287:3387server.2=172.16.114.135:2288:3388server.3=172.16.114.135:2289:3389
3.在 上一步 dataDir 指定的目录下,创建 myid 文件,然后在该文件添加上一步server 配置的对应 A 数字。
#zookeeper2181对应的数字为1#/opt/zookeeper2181/data目录下执行命令echo "1" > myid
4.zookeeper2182、zookeeper2183参照步骤2/3进行相应配置
5.分别启动三台服务器,检验集群状态
启动命令:./zkServer.sh start
登录命令:
./zkCli.sh -server 192.168.188.133:2181./zkCli.sh -server 192.168.188.133:2182./zkCli.sh -server 192.168.188.133:2183
测试,在2181端口,创建一个节点,看2182,2183是否能获取到该节点,如果能获取到,则说明zookeeper集群搭建成功。
2181端口:
2182端口: 2183端口:可以发现,zookeeper集群已经搭建成功。
zab协议 的全称是 Zookeeper Atomic Broadcast (zookeeper原子广播)。zookeeper 是通过 zab协议来保证分布式事务的最终一致性。
基于zab协议,zookeeper集群中的角色主要有以下三类,如下表所示:
zab广播模式工作原理,通过类似两阶段提交协议的方式解决数据一致性:在我们搭建的环境中,2182是作为领导者节点存在的(leader),2181和2183节点是作为跟随着节点存在的(follower)。如下图所示:
比如说,我们在2181服务中写数据,2181会发送一个请求给2182,2182会根据上面6个步骤,将数据写入集群中。looking:寻找leader状态。当服务器处于该状态时,它会认为当前集群中没有leader,因此需要进入leader选举状态。
leading: 领导者状态。表明当前服务器角色是leader。
following: 跟随者状态。表明当前服务器角色是follower。
observing:观察者状态。表明当前服务器角色是observer。
在集群初始化阶段,当有一台服务器server1启动时,其单独无法进行和完成leader选举,当第二台服务器server2启动时,此时两台机器可以相互通信,每台机器都试图找到leader,于是进入leader选举过程。选举过程如下:
对于Server1而言,它的投票是(1, 0),接收Server2的投票为(2, 0),首先会比较两者的zxid,均为0,再比较myid,此时server2的myid最大,于是更新自己的投票为(2, 0),然后重新投票,对于server2而言,其无须更新自己的投票,只是再次向集群中所有机器发出上一次投票信息即可。
统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于server1、server2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了leader
改变服务器状态。一旦确定了leader,每个服务器就会更新自己的状态,如果是follower,那么就变更为following,如果是leader,就变更为leading。
在zookeeper运行期间,leader与非leader服务器各司其职,即便当有非leader服务器宕机或新加入,此时也不会影响leader,但是一旦leader服务器挂了,那么整个集群将暂停对外服务,进入新一轮leader选举,其过程和启动时期的Leader选举过程基本一致。
假设正在运行的有server1、server2、server3三台服务器,当前leader是server2,若某一时刻leader挂了,此时便开始Leader选举。选举过程如下:observer角色特点:
除了这种简单的区别之外,观察者的功能与跟随者的功能完全相同-客户端可以连接到观察者,并向其发送读写请求。观察者像追随者一样将这些请求转发给领导者,但是他们只是等待听取投票结果。因此,我们可以在不影响投票效果的情况下尽可能增加观察员的数量。
观察者还有其他优点。因为他们不投票,所以它们不是ZooKeeper
选举中的关键部分。因此,它们可以在不损害ZooKeeper
服务可用性的情况下发生故障或与群集断开连接。给用户带来的好处是,观察者可以通过比跟随者更不可靠的网络链接进行连接。实际上,观察者可用于与另一个数据中心的ZooKeeper
服务器进行对话。观察者的客户端将看到快速读取,因为所有读取均在本地提供,并且由于缺少表决协议而需要的消息数量较小,因此写入会导致网络流量最小。
为了使用observer角色,在任何想变成observer角色的配置文件中加入如下配置:
peerType=observer
并在所有server的配置文件中,配置成observer模式的server的那行配置追加:observer,例如:
server.3=172.16.114.135:2289:3389:observer
ZooKeeper(String connectionString, int sessionTimeout, Watcher watcher)
代码如下:
public class ZookeeperConnection { public static void main(String[] args) { try { //计数器对象 CountDownLatch countDownLatch = new CountDownLatch(1); //参数1:服务器的ip和端口 //参数2:客户端与服务器之间的会话超时时间,以毫秒为单位的 //参数3:监视器对象 //Zookeeper对象是以异步的方式创建的 ZooKeeper zooKeeper = new ZooKeeper("172.16.114.135:2181,172.16.114.135:2182,172.16.114.135:2183", 5000, new Watcher() { @Override public void process(WatchedEvent event) { if(event.getState() == Event.KeeperState.SyncConnected){ //说明客户端与服务端连接对象创建成功了 System.out.println("连接创建成功"); //通知计数器对象不要再阻塞主线程了,可以继续往下执行了。 countDownLatch.countDown(); } } }); //主线程阻塞等待连接对象的创建成功 countDownLatch.await(); //打印客户端和服务器的会话ID System.out.println(zooKeeper.getSessionId()); //释放资源 zooKeeper.close(); }catch (Exception e){ e.printStackTrace(); } }}
转载地址:http://spiwi.baihongyu.com/