目录
ZK保证什么
总结下来来说,
对于写操作,ZK保证同一个客户端的写是顺序的,原子。而且数据一旦被写入就是持久的。
“同一个客户端”很重要,因为ZK无法确保多个客户端的时钟,所以无法保证多个客户端的写顺序。
“同一个客户端”指的是同一个会话,多个线程的会话,或者一个线程的多个会话都是无法保证?的。
对于读操作,同一个客户端从不同的服务器上读到的信息是一致的,而且在“一定的时间”之后肯定可以读到最新的数据。
不同的客户端可能会读到不同的数据,如果要保持两个客户端的数据的一致性,要使用sync( )函数。
会话保持
心跳机制源码:https://www.cnblogs.com/donganwangshi/p/4233538.html
MAX_SEND_PING_INTERVAL:默认10s,org.apache.zookeeper.ClientCnxn中使用final写死客户端的心跳时间间隔。
ticktime:默认3000ms,ZookeeperServer中配置的DEFAULT_TICK_TIME。"zookeeper/conf/zoo_sample.cfg中可以配置,用于服务器之间、服务器与客户端之间的心跳时间间隔。"--来自于网上博客,正确性有待确定,因为和MAX_SEND_PING_INTERVAL的功能冲突(这个是从源码中看到的),而且《从paxos到Zookeeper》这本书中的“技术内幕-会话”章节中也不是这么说的。
sessionTimeout:zookeeper中没有默认,要求用户必须传入。CuratorFrameworkFactory的默认是60*1000ms。设置的sessionTimeout未必会生效,服务器会将这个值限定在2*ticktime到20*ticktime之间。
connectionTimeoutMs:curatorClient独有的参数,默认15ms,如果curatorClient超过15s处于disconnect则会抛出一个lossexception,但client其实还是会有重连server的机会的。
zookeeper的会话
zookeeper的state?
https://bigdata.163yun.com/product/article/47
client和server的连接会产生一个session,一旦client发现无法连接server就叫LOSS_Connection,变为disconnect状态,并自发的产生一个disconnect事件。client接下来进入重连阶段,
-
如果在sessionTimeout之前连接上了server,那么client重新进入connect状态,服务器还会给客户端一个SyncConnected event。
-
如果在sessionTimeout之后连接上了,那么客户端会收到一个Expired event,状态变为expired。
-
如果一直无法连接server,那么client是不会再有反应了,一直保持disconnect状态。
curator的state?org.apache.curator.framework.state.Connectionstate
curator的state和上面讲解的会话保持过程息息相关。
connectionTimeoutMs
CuratorZookeeperClient是对zookeeper的封装,仔细观察,这个client比原生的ZookeeperClient的参数多了connectionTimeoutMs参数。那么这个参数应该是curator自己用的,而不是给zookeeper用的。connectionTimeoutMs(默认是15*1000ms),这个参数是做什么用的?有两处用到了这个参数。这两处都是在session过期之前,判断丢失连接的时间,然后超过connectionTimeout就会抛出异常。
curator的isConnect
curator有两处有isConnect函数。
一个是在CuratorZookeeperClient中,最终这个状态由org.apache.curator.ConnectionState中的checkState决定,这个函数根据zk的Event.KeeperState做相应的处理。SyncConnected、ConnectedReadOnly会返回true,Disconnected,AuthFailed,Expired,SaslAuthenticated返回false。
一个是org.apache.curator.framework.state.ConnectionStateManager中,这个最终会调用枚举变量org.apache.curator.framework.state.ConnectionState(注意和上个ConnectionState不在一个包里)中的isConnected方法。
zookeeper.KeeperException.ConnectionLossException 和 curator.CuratorConnectionLossException?
ConnectionLossException是当client和server已经断开连接之后,如果client调用setData等操作就会抛出这个异常。(发生在session过期之前)
CuratorConnectionLossException是curator如果失去连接超过connectionTimeoutMs之后抛出的异常。
需要注意的是,在抛出CuratorConnectionLossException的时候可能curator的状态并不是LOSS,因为从前面来看,只有session过期才会认定为LOSS状态。
LeaderSelector?LeaderLatch?
- 适用场景:
leaderSelector的核心函数是takeLeaderShip,当这个函数执行完毕的时候,client会放弃leader身份,所以leaderSelector适用于多个机器交替成为主的场景。
LeaderLatch的核心函数是isLeader和notLeader,client成为leader之后一般不会主动放弃leader身份。
- 公平选主:
leaderSelector是公平选主,也就是每个参与者轮流成为leader,一个client放弃leader之后,只有其他所有client都成为一次leader之后,才会有机会成为leader。
LeaderLatch每一轮都是新的随机竞选。
- 对stateChange的处理:
leaderSelector由用户实现stateChanged的逻辑。
LeaderLatch:已经有自己的实现,当网络波动时先放弃leader身份,重连的时候再重新竞选。
参考博客
curator的监听
https://my.oschina.net/thinwonton/blog/1036321
https://www.jianshu.com/p/70151fc0ef5d
zookeeper的连接管理
https://blog.csdn.net/jiyiqinlovexx/article/details/42469293
curator对连接状态的管理
https://blog.csdn.net/jiyiqinlovexx/article/details/42592605
注意事项
https://www.cnblogs.com/lee-mj/p/5073433.html
https://blog.csdn.net/odailidong/article/details/46473695
https://segmentfault.com/a/1190000017300219
https://juejin.im/post/5b593602f265da0f98315fb3
http://kenny7.com/2012/11/zookeeper-usage-notes.html
在String和byte[]进行转换的时候要使用utf-8
value.getBytes(Charset.forName("UTF-s"));
Watcher是一次性的,需要不断的重新计算
调用zookeeper的api进行操作时可能会抛出异常,需要根据异常的情况进行相应的重试
客户端收到异常时,发出的操作可能已经执行成功,但没有返回给客户端。在一些场景下需要做一些处理,比如使用create方法实现锁服务:如果抛出异常肯定是要重新尝试create,但是此时可能session已经成功创建了一个锁,如果还使用一样的逻辑重试就会导致所有的会话都拿不到锁。(本质是非幂等操作的问题?)
数据大小不能超过1M
问题
怎样构造批量更新(批量更行对于ZK是具有原子性质的)
客户端发生网络故障的整个过程,什么时候删除临时节点,什么时候发送watch事件,客户端什么时候抛出异常
操作-事件-watcher之间的对应关系