开源,分布式,为分布式框架提供协调服务,等价于:文件系统+通知机制
- 工作机制
- 服务端节点启动时,向ZK注册信息【临时节点】
- Client 获取当前服务器列表,并注册监听
- 当服务器节点下线
- ZK 通知Client
- Client 重新获取服务器列表,并注册监听
- 特点
- 主从架构,一个Leader,多个Follower
- 半数以上节点存活,ZK 集群正常工作
- 全局数据一致,每个Server存一份相同数据副本
- Client更新请求,顺序执行
- 数据更新具有原子性
- 实时性,最新数据
- 数据结构:类似Unix文件系统
- 一个ZNode 默认 存储 1MB 数据
- 每个ZNode 都有唯一标识
- 功能场景
- 统一命令服务
- 统一配置管理
- 统一集群管理
- 服务器动态上下线
- 软负载均衡
环境准备:JDK
- 下载安装包
- 解压安装包
- 修改配置文件 zoo.cfg
# 集群通信心跳时间ms tickTime=2000 # Leader 和 Follow 初次初始化时间 10*tickTime initLimit=10 # Leader 和 Follow 同步时间 5*tickTime syncLimit=5 # Zk 数据存放目录 dataDir=/opt/module/apache-zookeeper-3.5.7-bin/zkData # Zk 通信端口 clientPort=2181
- 启动Server、Client
# start server zkServer.sh start # start client zkCli.sh # quit client quit # zk status zkServer.sh status # stop server zkServer.sh stop2.2 集群安装
在本地基础上,做出如下修改
- 在zkData 目录下新建 myid 文件,里面输入本机id标识,可随意,后面对应上即可,分发
- 在zoo.cfg中加入如下配置,然后分发
# server.A = B:C:D A 为myid中的标识,B 为节点IP,C为信息交换端口,D为选举端口 server.2=hadoop102:2888:3888 server.3=hadoop103:2888:3888 server.4=hadoop104:2888:3888
- 在三台节点启动server
zkServer.sh start # 查看各节点身份(leader,follower) zkServer.sh status3. Zeekeeper 选举机制
3.1 第一次启动SID 服务器ID
ZXID 事务ID
Epoch Leader任期代号
- ZK1 启动,给自己投一票,不足一半票,LOOLING状态
- ZK2 启动,ZK1,ZK2 分别给自己投一票,ZK1 发现ZK2 的myid比自己大,把票投给ZK2,ZK2 两票,ZK 获得半票,成为Leader,ZK1 为Follower
- ZK3 启动,此集群已有Leader,ZK3自动成为Follower
- Epoch 任期代号大的,直接胜出
- Epoch 相同时,ZXID 大的,胜出
- ZXID 相同时,SID 大的,最终胜出
#!/bin/bash case in "start" ) for i in hadoop102 hadoop103 hadoop104; do echo "----------- start -------" ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh start" done ;; "stop" ) for i in hadoop102 hadoop103 hadoop104; do echo "----------- stop -------" ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh stop" done ;; "status" ) for i in hadoop102 hadoop103 hadoop104; do echo "----------- status -------" ssh $i "/opt/module/zookeeper-3.5.7/bin/zkServer.sh status" done ;; * ) echo "Args Error" esac5. Zookeeper Shell *** 作
# 连接 client zkCli.sh # 查看zk节点信息 ls -s / cZxid = 0x0 ctime = Thu Jan 01 08:00:00 CST 1970 mZxid = 0x0 mtime = Thu Jan 01 08:00:00 CST 1970 pZxid = 0x0 cversion = -1 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 0 numChildren = 1
- 节点类型
- 临时、永久
- 有序号、无序号
# 节点 *** 作:创建节点 create /hefei "shushan" # 无序号永久节点 create -s /hefei "shushan" # 有序号永久节点 create -e /hefei "gaoxin" # 无序号临时节点 create -e -s /heifei "gaoxin" # 有序号临时节点 # 节点 *** 作:查看节点值 get -s /hefei # 节点 *** 作:修改节点值 set /hefei "gaoxin" # 节点 *** 作:删除节点 delete /hefei deleteall /hefei # help help6. Zookeeper 监听器
- 工作流程
- 首先Main(),在main线程内部创建 Zk client ,两个线程:conncet、listener
- connect 连接ZK server,发送监听事件
- ZK server 把连接路径注册到监听器列表
- 当列表发生变化时,回调给listener
- listener调用内部process()方法处理变化
- 常见监听场景
-
节点数据变化
get -w path
-
节点增减变化
ls -w path
7. Zookeeper API注意:注册一次,只生效一次,只能监听一次
package com.ipinyou.zookeeper; import org.apache.zookeeper.*; import org.apache.zookeeper.data.Stat; import org.junit.Before; import org.junit.Test; import java.io.IOException; import java.util.List; public class ZkClient { public String connectString="hadoop102:2181,hadoop103:2181,hadoop104:2181"; public int sessionTimeout = 60000; private ZooKeeper zkClient; @Before public void init() throws IOException { zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() { public void process(WatchedEvent event) { } }); } @Test public void create() throws KeeperException, InterruptedException { zkClient.create("/anqing","aaa".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } @Test public void getChildren() throws KeeperException, InterruptedException { List8. Zookeeper 写数据流程 8.1 Client 发送写请求给Leaderchildrens = zkClient.getChildren("/", true); for (String children : childrens) { System.out.println(children); } } @Test public void exists() throws KeeperException, InterruptedException { Stat exists = zkClient.exists("/anqing", false); System.out.println(exists != null? true: false); } }
- Leader 接收到写请求,写入数据,发送给其他Follower写,当超过半数ack应答成功之后
- Leader 给Client 回复ack 写成功
- Follower 接收到写请求,发送给Leader写数据,Leader写完之后,发送给此Follower写数据
- 当超过半数应答成功之后,Leader 给接收到Client请求的那个Follower 回复ack
- 最后有此Follower 给Client 回复ack 写成功
- ZK 创建一个永久节点
- 服务器在此节点下注册临时节点
- Client 监听此节点下 上下线变化
- ZK 创建一个永久节点
- 各个Client 在启动时在此节点下创建有序号临时节点
- Client 判断自己是不是最小节点,是,得到锁;不是的话,对前一个节点进行监听
- 最小节点处理完业务释放锁,节点删除,下面的节点继续处理
是不是最小节点的实现思路:
判断当前路径下节点,如果就一个,那就是最小,如果不是,获取到当前节点在列表中的位置,找到前一个节点,在监听process()方法中如果监听到了节点删除 *** 作并且节点是当前节点的上一个节点,那此时此节点最小,得到锁
11. Zookeeper 数据一致性 11.1 Paxos 算法对于分布式锁的处理,有成熟的处理框架 Curator
11.2 ZAB 协议一种基于消息传递的、具有高容错性的一致性算法
问题:当集群中出现一个以上的Proposer,有可能会出现活锁现象
11.3 CAP理论Zookeeper 的基层协议,集群中只有一个Leader
C :一致性 多个副本之间保持数据的一致性
A : 可用性 服务一直处于可用状态
P : 分区容错性 在网络分区故障时,仍能对外提供满足一致性和可用性的服务
Zookeeper 满足 CP ,ZK 不能保证每次服务请求可用,且 Leader选举阶段集群不可用
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)