目录
ZK原生API
1. api是异步连接,但可以同步创建节点
2. 保存字节数组
3. 不能递归创建节点,只能在父节点下面创建子节点
4. 只能删除叶子节点
5. 事件通知要反复注册Watcher,客户端需要反复调用方法去注册(因为服务端保存Watcher在列表里,每次触发会做清理,如果不清理的话遇到一些更新频繁的数据就要触发很多Watcher,这就影响了服务端的性能)
ZkClient
做了封装,让开发人员更方便使用zk的
1. 连接是同步
2. 保存数据是对象
3. 可递归创建节点,逐层创建父节点
4. 可删除非叶子节点
5. 使用程序员更熟悉的Listener来接收通知,只需要注册一次就会一直生效
叶子节点的监听和限制
非叶子节点必须为持久节点
无法对二级节点做事件监听root/c1/c2 监听c1时,不能对c2的变动做监听
Curator客户端
基本拥有ZkClient的优点。可读性更强的Fluent风格的客户端,解决ZK客户端非常底层的细节开发工作,包括连接重连,反复注册Watcher,NodeExistsException异常(创建已经存在的节点抛出异常)
1. 可做master选举
2. 分布式锁
3. 分布式计数器:有可能累加失败,需要做好判断:
4. 分布式barrier:可能是创建临时节点,统计节点数目达到设定的值就一起执行
ZK的典型应用场景
1. 数据发布/订阅
2. 负载均衡-DNS服务
3. 命名服务,类似于唯一键。UUID的弊端是长度过长(相比较于int)和含义不明。原理:使用zk的顺序节点唯一性
4. 分布式协调/通知。MySQL数据复制总线:Mysql_Replicator,热备份:多台机器创建临时顺序节点,如果是发现自己节点的序号是最小的则RUNNING,否则STANDBY待机,同时监听节点变化。冷备份:不需要一对一的STANDBY机器,只要少量STANDBY机器遍历目录,同时创建临时节点,如果发现自己序号是最小则替代原来的机器,状态变为RUNNING,这样就可以节省机器资源。
5.集群管理。可以看到当前集群有多少机器,收集运行时状态数据,对集群做上下线操作。
ZK两个特性
1. 对一个节点做Watcher监听,只要节点及其子节点变化,则会向订阅的客户端发送更新通知。
2.创建的临时节点,会话失效时,临时节点会自动清除。
ZK加锁和master选举原理
master选举原理:创建一个临时节点,创建成功则为master,其他客户端监听这个节点,一旦这个节点挂了会重新进行Master选举。
排它锁:跟master原理类似,创建一个节点,zk保证只有一个客户端创建成功。成功创建的就获得锁,没有获得锁的客户端对这个节点做监听。机器宕机或者释放锁时会释放锁。
读写锁:临时顺序节点,对于读锁:创建读节点,只要自己是最小或者比自己小的都是读节点,则获得读锁。对于写锁,自己是最小的则获得写锁。同时监听目录下节点的改变。
预防假死:使用ACL,延迟等待几秒再去争取Running(原来的主不延迟)
各个服务器角色介绍
Leader:事务请求的唯一调度和处理者,集群内部各服务器的调度者。请求处理链来处理各种请求,负责处理事务请求,记录事务请求到事务日志文件,生成数据快照。会与Follower/Observer服务器建立TCP长连接。每次master选举完会产生一个新的Leader周期,也就做纪元或者时代。Leader产生之前无法对外提供服务。
Follower:处理客户端非事务请求,转发事务请求给Leader服务器。参与事务请求Proposal的投票。参与Leader选举投票。
Observer:观察者角色,观察zk集群的最新状态变化并将这些状态变更同步过来,用来提升集群的非事务处理能力。原理和Follower基本一致,但是不参与任务投票。
数据与存储
ZKDatabase:内存数据库,定期向磁盘dump快照数据,zk启动时读取磁盘上的日志文件和快照数据文件。
事务日志文件:大小都是64M,后缀是一个事务ID,是写入文件的第一条事务记录的ZXID(高32位代表当前Leader周期,也叫做纪元或者时代,低32位是真正的操作序列号)。不会有读操作的记录。为了提高磁盘的I/O效率,文件不足4KB时会预分配一块大磁盘块,默认是64MB。非Leader的事务ID不能比Leader大,如果大于Leader则会做日志截断,要求跟Leader一致。
snapshot-数据快照:某一时刻的内存数据内容,后缀也是ZXID,是保存文件时zk的最新ZXID。没有预分配,每个内容都是有效的,大小可以反映zk的全量数据大小。
ZK初始化
1. 读取最新100个快照文件,从最大ZXID的文件开始解析校验文件是否正确,直到解析成功,如果所有解析都不成功就初始化失败。解析后读到最大的ZXID:zxid_for_snap
2. 读取事务日志文件,如果有比zxid_for_snap大的事务,则加载这些事务数据。
参考:《从Paxos到ZooKeeper分布式一致性原理与实践》