1. 什么是zookeeper?
分布式协调服务
- 是一个典型的分布式数据一致性解决方案,分布式应用程序可以基于 ZooKeeper 实现诸如数据发布/订阅、负载均衡、命名服务、分布式协调/通知、集群管理、Master 选举、分布式锁和分布式队列等功能。
- Zookeeper 一个最常用的使用场景就是用于担任服务生产者和服务消费者的注册中心
- ZooKeeper有临时节点的概念。 当创建临时节点的客户端会话一直保持活动,瞬时节点就一直存在。而当会话终结时,瞬时节点被删除。持久节点是指一旦这个ZNode被创建了,除非主动进行ZNode的移除操作,否则这个ZNode将一直保存在Zookeeper上
- 为了保证高可用,最好是以集群形态来部署 ZooKeeper,这样只要集群中大部分机器是可用的(能够容忍一定的机器故障),那么 ZooKeeper 本身仍然是可用的
- ZooKeeper 将数据保存在内存中,这也就保证了 高吞吐量和低延迟
- ZooKeeper 是高性能的。 在“读”多于“写”的应用程序中尤其地高性能,因为“写”会导致所有的服务器间同步状态。(“读”多于“写”是协调服务的典型场景。)
2. 会话是什么?
- 在 ZooKeeper 中,一个客户端连接是指客户端和服务器之间的一个 TCP 长连接
- 通过这个连接,客户端能够通过心跳检测与服务器保持有效的会话,也能够向Zookeeper服务器发送请求并接受响应,同时还能够通过该连接接收来自服务器的Watch事件通知
- 只要在
sessionTimeout
规定的时间内能够重新连接上集群中任意一台服务器,那么之前创建的会话仍然有效。
在为客户端创建会话之前,服务端首先会为每个客户端都分配一个sessionID。由于 sessionID 是 Zookeeper 会话的一个重要标识,许多与会话相关的运行机制都是基于这个 sessionID 的,因此,无论是哪台服务器为客户端分配的 sessionID,都务必保证全局唯一。
3. 节点Znode
(1) 分布式系统的节点是类似 Leader 和 slave 的主从节点, 但是zookeeper确实不同它是存放数据的数据单元节点
(2) 节点分成两种:
1) 临时节点, 一次会话(session)创建出来的节点, 随着session 的消失而消失
2) 持久节点: 一但创建, 如果不主动删除, 它将永远一直zookeeper上
在添加节点的时候每个节点会被zookeeper标记上SEQUENTIAL(一个整型自增)
(3) 每个节点都会存在一个Stat数据结构, 用来记录Znode的三个版本, 当前Xnode, 当前Znode子版本, 当前Znode的ACL版本
4. 事件监听器
zookeeper会在某些节点上注册事件监听器, 当满足某些条件的时候就会主动通知一些客户端, 该机制是Zookeeper实现分布式协调服务的重要特性。
5. ALC访问控制列(AccessControlLists)

6. zookeeper的特点
- 顺序一致性: 从同一客户端发起的事务请求,最终将会严格地按照顺序被应用到 ZooKeeper 中去。
- 原子性: 所有事务请求的处理结果在整个集群中所有机器上的应用情况是一致的,也就是说,要么整个集群中所有的机器都成功应用了某一个事务,要么都没有应用。
- 单一系统映像 : 无论客户端连到哪一个 ZooKeeper 服务器上,其看到的服务端数据模型都是一致的。
- 可靠性: 一旦一次更改请求被应用,更改的结果就会被持久化,直到被下一次更改覆盖。
7. zookeeper内部数据结构类型window的文件系统

上面的每一个节点都是Znode, 但是这个数据结构却是存放在内存中的, 所以和文件系统又不同, 速度比较快
8. zookeeper是可集群
(1) 它的集群使用的是Zab(Zookeeper Atomic Broadcast)来确保高可用的, 如果其中的leader无法接通了, 那么将会通过这个集群选举策略来选举新的leader, 而且集群是需要奇数数量的节点的
(2) 客户端和zookeeper是通过TCP进行连接的, 使用心跳包完成的判断
9. 顺序访问
zookeeper可以保证客户的每个请求的先后顺序, 保证先后顺序使用的是叫做时间戳的方式保证的顺序执行也叫zxid(Zookeeper Transaction Id)也叫zookeeper事务id
10. zookeeper集群角色


过半写成功???
11. zookeeper使用的是ZAB协议
zab协议存在两种模式, 一个是崩溃恢复模式和消息广播模式, 两个模式
崩溃恢复模式:
当集群中唯一的leader失效的时候, zab将会转化成崩溃模式, 崩溃模式下zab将会选举出新的leader, 当集群中有过半的节点完成了同步后, Zab将退出恢复模式, 转成消息广播模式
消息广播模式:这个模式下, leader将会把读取的操作丢给follower去完成, 当这个操作是写的使用, follower将把这个事务丢给leader
12. zookeeper的缺陷
(1) zookeeper的设计理念使用的是CAP中的CP, 保证了单调一致性, 所以在一些极端环境下, zookeeper可能会丢掉一些请求, 但是它能保证数据的一致性和顺序性
1) 因为它在选举是当一半的N + 1 个follower发现你是leader的时候就会开始围绕着leader工作, 但是还有部分并不知情的节点;2) 当数据同步的时候, 当数据同步达到 N/2 + 1 的情况下, zookeeper便表示可以使用这个数据了, 因为他是最新的, 但是实际上还有部分节点存储的是旧值
C: zookeeper它只能保证在十几秒到几分钟的时间后数据是最终一致的
A: 数据是可用了, 无任何的锁结构, 有大半的节点存储的是最新的值, 如果你想保证拿到的所有节点的值都是最新的, 那么可以调用Sync() 去同步获取最新的值
P: 节点多了, 同步数据的时间会变长, leader的选取需要大量的时间, 但是可以引入Observer节点临时缓冲下数据, (前文说过Observer不进行选举)
(2) zookeeper可能还存在脑裂问题, 就是多个leader的问题
(3) 当zookeeper判断一个节点失效了, 那么它会直接将zookeeper剔除出这个集群, 这样会出现一个问题, 有可能剔除出去的这个节点并不是不可用的, 但是你直接把他剔除出这个集群, 也许这个节点正在和某个客户进行联系, 或者这个节点出现了网络故障的问题, 这个问题是临时的, 等待期网络恢复后便可以继续使用了, 但是zookeeper的集群被踢出的节点恢复正常是无法自动进入这个集群的, 不想eurake使用了节点保护机制, 暂时保护了这个节点, 让其保存在集群中(当然新的请求是不能再去请求它了), 等待这个节点恢复后, 新的请求将可以送到这个节点进行处理