Zookeeper基础
一、概叙
Zookeeper是一个开源的、分布式的,为分布式应用提供协调服务的框架。
Zookeeper是文件系统+通知机制。
Zookeeper从设计模式来讲是一个观察者模式设计的分布式服务管理框架。
二、特点
- 一个leader和多个follower组成
- 集群达到半数以上的机器存活即可正常运行
- 全局一致性
- 数据更新原子性,一次数据更新要么成功,要么失败
- 实时性,能读到最新数据
- 数据结构是类似于Unix文件系统的树形结构
三、应用场景
- 统一命名服务
- 统一配置管理
- 统一集群管理
- 服务节点动态上下线
- 软负载均衡
四、API应用
-
添加pom文件
<dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>RELEASE</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.8.2</version> </dependency> <dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.10</version> </dependency> </dependencies>
-
拷贝log4j.properties文件到项目根目录
log4j.rootLogger=INFO, stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n log4j.appender.logfile=org.apache.log4j.FileAppender log4j.appender.logfile.File=target/spring.log log4j.appender.logfile.layout=org.apache.log4j.PatternLayout log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
-
创建ZooKeeper客户端
private static String connectString ="hadoop101:2181,hadoop102:2181,hadoop103:2181"; private static int sessionTimeout = 2000; private ZooKeeper zkClient = null; @Before public void init() throws Exception { zkClient = new ZooKeeper(connectString, sessionTimeout, new Watcher() { @Override public void process(WatchedEvent event) { // 收到事件通知后的回调函数(用户的业务逻辑) System.out.println(event.getType() + "--" + event.getPath()); // 再次启动监听 try { zkClient.getChildren("/", true); } catch (Exception e) { e.printStackTrace(); } } }); }
五、节点类型
-
永久节点
-
临时节点
-
永久有序节点
-
临时有序节点
注意:在分布式系统中,顺序号可以被用于所有的事件进行全局排序,这样客户端可以通过顺序号来推断事件的发生顺序
六、Stat结构体(了解)
-
czxid-创建节点的事务zxid
每次修改ZooKeeper状态都会收到一个zxid形式的时间戳,也就是ZooKeeper事务ID。
事务ID是ZooKeeper中所有修改总的次序。每个修改都有唯一的zxid,如果zxid1小于zxid2,那么zxid1在zxid2之前发生。
-
ctime - znode被创建的毫秒数(从1970年开始)
-
mzxid - znode最后更新的事务zxid
-
mtime - znode最后修改的毫秒数(从1970年开始)
-
pZxid-znode最后更新的子节点zxid
-
cversion - znode子节点变化号,znode子节点修改次数
-
dataversion - znode数据变化号
-
aclVersion - znode访问控制列表的变化号
-
ephemeralOwner- 如果是临时节点,这个是znode拥有者的session id。如果不是临时节点则是0。
-
dataLength- znode的数据长度
-
numChildren - znode子节点数量
七、监听器原理(面试重点)
- 首先有一个main()线程
- 在main中创建zookeeper客户端,在客户端下会自动创建两个线程,一个是用于网络连接通信的connect线程,一个是用于负责监听的listener线程
- 通过connect线程把注册的监听事件发送给zookeeper
- zookeeper会把接收到的事件添加到监听器列表中
- 一旦需要监听的事件发生变化,zookeeper会把监听结果的消息发送给listener线程
- listener线程内部调用了process方法
- 最后系统会根据变化做出相应的调整
八、zookeeper选举机制(面试重点)
- 半数机制:集群中半数以上机器存活,集群可用;所以Zookeeper适合安装奇数台服务器。
- 具体过程:
- 假设有三台机器,它们myid分别为1,2,3
- 当第一台机器打开时,会投自己一票,此时第一台机器票数是1
- 当第二台机器打开时,也会投自己一票,同时根据myid的大小,第一台机器会把自己的一票投给第二台机器,此时第一台机器为0票,第二台机器为2票,而此时票数已经超过集群机器数的一半,所以第二台机器选举为Leader,第一台机器成为Follower
- 当第三台机器打开时,由于前两天机器状态不是Looking,自己也随之成为Follower
九、写数据流程
- zookeeper客户端向zookeeper集群上的某个机器写入数据
- 如果这台机器不是Leader,它会把写数据的请求发送给Leader,Leader接收到信息后,会以广播的形式把需要写数据的请求发送给各个Follower,每个Follower接收到信息后加入待写队列,等待写入数据,并向Leader发送成功消息
- 当Leader接收到一半以上的Follower发送的信息后,说明该操作可以执行,然后会向各个Follower发送提交信息,各个机器收到消息后会落实队列里的写请求,此时写数据成功
- 最后各个机器会进一步通知客户端写数据成功