zk是什么
zk是一个开源的、分布式的程序协调服务,是Google的chubby的一个开源实现,
用来做集群的管理,监视集群中各个节点的状态,并在节点发生变化时会通知订阅了关注的客户端
他还暴露了其简单易用、性能高效、稳定的的api给客户端,zk是一个cap理论中的cp系统
读请求:读请求可以被任意一个zk集群实例单独完成处理,如果在目录节点上注册了监听器,这个监听器也是由连接的zk实例处理
写请求:写请求会发送所有的zk集群的实例,并且在达成一致后请求才会返回给客户端成功
因此,随着zk集群的实例增多,zk的读性能在上升,写性能在下降
有序性是zk一个重要的概念,zxid是一个64位的编号,高32位是epoch(时期;纪元;世;新时代),低32位是自增的编号
所有的更新操作都有对应一个zxid(zk transaction id),对于写请求每次都会返回一个一个递增的zxid,对于读请求会返回当前最新的zxid
zxid被用在处理zk集群的数据一致性、判断leader、实现顺序编号、保证数据持久性、实现数据同步等方面
zk提供的核心工厂
- 目录树结构api(每个节点最大保存1m数据)
- 通知机制
zk中的目录树节点类型
- persistent:持久化节点,创建的客户端断开,节点依旧存在
- persistent-sequential:持久化顺序编号目录节点,创建的客户端断开,节点依旧存在,而且zk回给该节点名称进行顺序编号
- ephemeral:临时性节点,创建的客户端断开连接,节点即被删除
- ephemeral-sequential:临时性顺序节点,创建的客户端断开连接,节点即被删除,并且zk会给该节点名称进行顺序编号
zk可以做什么
- 集群管理(临时顺序节点+通知机制,新增节点就是集群注册功能,leader节点下线时选择最小的节点作为master)
- 命名服务(比如创建一个节点表示xx集群)
- 配置管理(创建一个节点,并在节点上保存配置信息)
- 分布式锁(利用实现公平锁:临时顺序节点+通知机制,解锁时会触发删除节点事件,然后最小的顺序节点获取到锁)
- 队列管理(利用持久化顺序节点+通知机制,有节点加入通知消费者获取最小的节点,消费成功后删除最小节点)
zk的复制原理
- 写主(write master):对写要提交给leader节点,读无限制,可读取任意节点,这种情况下客户端要对读写进行区分,俗称:读写分离
- 写任意(write any):对数据的修改可以提交给任意节点,和读一样
zk的相应能力取决哪种实现方式,是异步复制保证性能,还是同步复制保证数据安全
zk的工作原理
zk的核心是原子广播,这个机制保证各个server之间的同步,实现这个机制的叫zab协议。zab协议有两种模式,恢复模式(选主)和广播模式(同步)。
恢复模式是在集群启动或者集群奔溃后恢复进行,当leader被选出来且大多数server和leader状态同步后,恢复模式结束;
状态同步保证了leader和follower具有相同的系统状态
zk的server工作状态
有三种状态:
- LOOKING:不知道leader是谁,正在搜寻
- LEADING:当前server就是leader
- FOLLOWING:leader已经选出来,当前server作为跟随者,同步leader的状态
zk选择leader的详细过程
当leader奔溃或者leader失去大多数follower,这是zk进入恢复模式,恢复模式又两种算法:basic paxos和fast paxos
fast paxos和basic paxos的区别就是:fast paxos直接推荐自己为leader,
而basic paxos则第一轮征集所有的follower推荐,选择出最大的zxid,第二轮投票表决是否大于n/2+1个同意,通过则成为leader
zk的同步过程
选择完成leader,zk进入同步过程
- leader等待follower连接
- follower连接上leader,并把最大的zxid发送给leader
- leader根据接收到的zxid确认最后同步点
- 完成通知后,follower变更为uptodate状态
- follower变更为uptodate状态,就可以开始接受client请求
zk的节点宕机如何处理
- 最少3个节点,保证高可用性
- follower宕机,还有其他副本可以使用,不影响
- leader宕机,会重新选择leader,只要剩余的节点大于等于n/2+1个,所以3个节点的集群最多整你宕机1个节点,宕机两个节点集群将无法工作
zk的watch机制
watch事件时一次性通知,当监听的节点数据发生变动时一次性通知给client
watch机制特性:
- 一次性通知,由于客户端本身问题或者网络问题没有收到通知,并不会收到二次通知
- 数据监视分为两种:数据监视和子数据监视,数据监视注册用:getdata()、exists(),字节数监视注册用:getchildren();
- 通知触发有:setData、create、delete;setData会触发set节点的watch,create会触发create节点的watch和父节点的child watch,
delete会触发delete节点的watch,父节点的watch和delete子节点的watch - 当client断开期间丢失的watch将无法再被接收到,但是重连后如果需要恢复先前的watch注册,是可以的