基础
-
介绍:
- 分布式应用程序协调服务,通过共享内存的方式解决集群中的一致性问题,可以实现统一命名,状态同步,分布式锁,集群管理
- 为弱一致性,可以达到最终一致性
- 使用类似文件系统的方式来存储数据,
- 可以监听数据节点的变化,并在节点发生变化时通知到在该节点上注册的客户端,通过这种方式来进行管理
-
节点:
- 在zookeeper中,信息被保存在数据节点中,即znode,其形式累次目录中的一个层次;采用了类似文件系统的层级树状结构进行管理
- 每个znode都有版本号,随着每次数据变化自增,可以使用版本号来达到原子性操作的目的,cas
- 节点分为四种类型,如下
- PERSISTENT-持久化目录节点:客户端与zookeeper断开联系后,该znode节点仍然存在
- PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点:与上同,且节点会被顺序编号
- EPHEMERAL-临时目录节点:客户端与zookeeper断开连接后,该节点被删除
- EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点:客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号
-
角色:
- client:客户端,可能时具体的服务实例或者不同的服务,为分布式中的一个节点,访问服务器的配置信息,周期性向server发送心跳包,server向client回应确认,如果client没有收到回应,则重定向到另一个server
- server:zookeeper中的一个节点,为client提供所需的服务,给client回应信息表明自己是存活的,该server与分布式系统中处理业务的服务不同
- server中分为leader,follower,observer
-
Watcher:
1. 使用通知机制而非轮询机制来得到znode节点的变化
2. Client可以在某个ZNode上设置一个Watcher,来Watch该ZNode上的变化。如节点本身的增加,删除,数据修改,以及孩子的变化,
3. 如果该ZNode上有相应的变化,就会触发这个Watcher,把相应的事件通知给设置Watcher的Client。
4. ZooKeeper中的Watcher是一次性的,即触发一次就会被取消,如果想继续Watch的话,需要客户端重新设置Watcher
5. Watcher 通知非常简单,只会告诉客户端发生了事件,而不会说明事件的具体内容。
6. 例如针对 NodeDataChanged 事件,ZooKeeper 的 Watcher 只会通知客户指定数据节点的数据内容发生了变更,而对于原始数据以及变更后的新数据都无法从这个事件中直接获取到,而是需要客户端主动重新去获取数据,这也是 ZooKeeper 的 Watcher 机制的一个非常重要的特性。
7. 客户端串行执行,客户端 Watcher 回调的过程是一个串行同步的过程 -
服务器状态:
- Looking状态:该状态下表示节点可以进行选举
- Following状态:由looking状态转换而来
- Leading状态:由looking状态转换而来
- Observer状态:该状态下的节点只进行读数据
-
事务ID:(zxid):leader节点会为每一个客户端提交的事务分配一个全局的事务id,并且该id是从0递增的。
-
集群:
- zookeeper集群中为了选举出一个主节点,集群搭建时必须要搭建3、5、7等奇数个节点,这样就可以通过相应的选举算法(paxos算法)选举出一个leader节点,用于管理整个集群,其他节点成为follower.
- 集群中的server分为leader和follewer,observer
- leader:Leader作为整个ZooKeeper集群的主节点,负责响应所有对ZooKeeper状态变更的请求。它会将每个状态更新请求进行排序和编号,以便保证整个集群内部消息处理的FIFO。
- follower:除了响应本服务器上的读请求外,follower还要处理leader的提议,并在leader提交该提议时在本地也进行提交。
- 另外需要注意的是,leader和follower构成ZooKeeper集群的法定人数,也就是说,只有他们才参与新leader的选举、响应leader的提议。
- Observer:如果ZooKeeper集群的读取负载很高,或者客户端多到跨机房,可以设置一些observer服务器,以提高读取的吞吐量。Observer和Follower比较相似,只有一些小区别:首先observer不属于法定人数,即不参加选举也不响应提议;其次是observer不需要将事务持久化到磁盘,一旦observer被重启,需要从leader重新同步整个名字空间。
-
主节点选举:
- 当leader崩溃或者leader失去大多数的follower,这时候zk进入恢复模式,恢复模式需要重新选举出一个新的leader,让所有的 Server都恢复到一个正确的状态。
- Zk的选举算法有两种:一种是基于basic paxos实现的,另外一种是基于fast paxos算法实现的,默认为fast
- 在恢复阶段,每台服务器从本地目录找自己所拥有的Zxid(最大事务id),每有一次操作,都是一个事务,每次事务都会递增,事务id越大,事务越新
- 每台zk服务器都会提交一个选举协议,协议中的内容:自己的zxid(事务id),选举id(myid文件里的数字),逻辑时钟值(和选举轮数有关),作用是确保每台zk服务器处于同一轮选举中,状态-(Looking)选举状态,Leader,Follower,Observer
- 选举PK原则, 先比较Zxid,谁大谁当Leader,如果Zxid比较不出来,再比较选举ID,谁大谁当Leader(前提是要满足过半机制)
- 选举完成后,会进行数据的同步
-
同步流程:
- 对于客户端的读请求,任何一个服务器都可以处理
- 对于写请求,会交给Leader来处理,Leader会通过原子广播端口,将写请求(事务)广播给其他的节点,还会收集每个zk服务器的ack信息,然后统计是否满足过半性,如果满足,则次事务成功提交,最后反馈给客户一个确认信息
-
会话:
- 客户端对zookeeper集群发送任何请求前,需要和zookeeper集群建立会话。
- 客户端提交给zookeeper的所有操作均关联在一个会话上。当一个会话因某种原因终止时,会话期间创建的临时节点将会消失。
- session 的 SessionTimeout 值用来设置一个客户端会话的超时时间。
- 当由于服务器 压力太大、网络故障或是客户端主动断开连接等各种原因导致客户端连接断开时,只要在 SessionTimeout 规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话 仍然有效。
- 会话提供了顺序保障。同一个会话中的请求以FIFO顺序执行。
- 并发会话的FIFO顺序无法保证。
-
实现分布式锁:
- 每个客户端往/exlusive_lock下创建有序临时节点/exlusive_lock/lock_。创建成功后/exlusive_lock下面会有每个客户端对应的节点,如/exlusive_lock/lock_000000001
- 客户端取得/exlusive_lock下子节点,并进行排序,判断排在最前面的是否为自己。
- 如果自己的锁节点在第一位,代表获取锁成功,此客户端执行业务逻辑
- 如果自己的锁节点不在第一位,则监听自己前一位的锁节点。例如,自己锁节点lock_000000002,那么则监听lock_000000001.
- 当前一位锁节点(lock_000000001)对应的客户端执行完成,释放了锁,将会触发监听客户端(lock_000000002)的逻辑。
- 此中方式为公平锁实现
注意点
- 使用分布式锁的方式来处理集群节点中的主从切换,获取到锁的节点作为主节点
- 在 ZooKeeper 中,一个客户端连接是指客户端和 ZooKeeper 服务器之间的TCP长连接。