第3章
Session的处理注意点:
如果session不再需要使用,需要立刻[b]close[/b]
[b]CONNECTIONLOSS[/b]
客户端与zk service的连接断开,也就是TCP连接已经断开了。这时候如果进行原语操作,比如create等,就会出现CONNECTIONLOSS。
CONNECTIONLOSS的出现,会引起不确定的问题:即:之前的原语操作是否成功, 有如下3种情况:
1. 原语操作还没有发给服务端
2. 原语操作已经发给服务端,但是服务端还未执行
3. 原语操作已经发给服务端,服务端也执行了,但是客户端没有收到结果
因此应用在处理CONNECTIONLOSS时,需要容错这3种情况,实际上是2种情况,即:操作成功/失败的状态,是不确定的。
有2种处理方式:
1. 可以选择校验看是否成功,比如之前setData,现在可以getData进行确认;
2. 不在乎结果,那就重试发送。
总结:
Remember, ZooKeeper helps organize distributed state and provides a framework for handling failures; it doesnt make failures go away, unfortunately.
第4章
轮询不好,需要watch
watch是一次触发,比如exists原语,可以监控多个事件 create/delete/change,但是只要有1个事件触发,watch就结束了,而应用中很多时候是要连续watch,可参考curator等lib
一次触发,会不会导致丢失事件? 是会的,参考第2章的图,但是数据不会丢失。
watch生命周期是随着session的,只要session不过期,watch就是有效的。 比如zk server宕机,发生了重连,客户端的watch也会发给重连的zk server。 如果watch需要触发,则立刻触发,否则注册到zk server上。
session state:
SyncConnected
Disconnected
Expired
AuthFailed
ConnectedReadOnly
SaslAuthenticated
事件:
NodeCreated,
NodeDeleted
NodeDataChanged
NodeChildrenChanged
None
事件watch对应的操作原语:
NodeCreated
A watch is set with a call to exists.
NodeDeleted
A watch is set with a call to either exists or getData.
NodeDataChanged
A watch is set with either exists or getData.
NodeChildrenChanged
A watch is set with getChildren.
看一下示例代码:
这里主要是监控 session的状态变化,即 生命周期
/**
* This method implements the process method of the
* Watcher interface. We use it to deal with the
* different states of a session.
*
* @param e new session event to be processed
*/
public void process(WatchedEvent e) {
LOG.info("Processing event: " + e.toString());
// 事件为NONE,标明是Session状态变化
if(e.getType() == Event.EventType.None){
switch (e.getState()) {
case SyncConnected:
connected = true;
break;
case Disconnected:
connected = false;
break;
case Expired:
expired = true;
connected = false;
LOG.error("Session expiration");
default:
break;
}
}
}
这里是普通的exists API
// 判断事件类型
Watcher masterExistsWatcher = new Watcher(){
public void process(WatchedEvent e) {
if(e.getType() == EventType.NodeDeleted) {
assert "/master".equals( e.getPath() );
runForMaster();
}
}
};
watch设置后,是否可以删除呢? 目前无法直接删除,只能通过 session 过期 或者 主动close。
这个功能在3.5.0已经增加了,可以看下3.5.0的release notes:
http://zookeeper.apache.org/doc/r3.5.0-alpha/releasenotes.html
* [ZOOKEEPER-442] - need a way to remove watches that are no longer of interest
Description
currently the only way a watch cleared is to trigger it. we need a way to enumerate the outstanding watch objects, find watch events the objects are watching for, and remove interests in an event.
总结一下,watch可以用在2个地方:
1. 监视session的状态变化
2. 监视znode的节点变化
这里采用的是同一套机制,需要区分。 如果event是None,则是Session状态变化;如果event不是Node,则是znode变化
顺序性保证
写的顺序性
zk server对于写操作,是顺序进行的;在zk集群中,多个zk server的数据同步,也是按照顺序进行的,不会造成写乱序的情况。
当时因为延迟的情况,不能保证zk server的数据强一致,在某个时间点存在不一致的情况,比如某个数据还未同步过来。
读的顺序性
多个客户端,连接zk集群中不同的server,依然能保证按照顺序读到相应的修改。
但是因为 同步的不一致性, 不能保证同一个时间点,各个客户端读到的数据完全是一致的,一般来说,是没有问题的。 只有某个特殊情况会有问题,称为hidden channel,应该避免这种情况
notification的顺序性
第5章
对于失败,有不同的情况,这里说明一种情况:
假设是竞争/master,如果 当前的master因为网络等原因,与ZK已经断开连接,但是master不知道,还以为自己活着,而且自己做了master的事情。
而slave与zk是正常的, 从zk上发现/master已经挂掉了,就转换为master角色。
这时候出问题了,我们有2个master。 而如果某些操作 必须是互斥的,比如写文件, 这时候如果2个一起写,就导致数据错乱,系统挂掉了。
recoverable failures
unrecoverable failures
session过期
session认证错误
对于这种情况,只有2种处理方式:
1. 重启
2. 不重启,清除内部资源,重新初始化,重新创建session