本文地址:https://blog.csdn.net/WEI_GW2012/article/details/80398639
在很多分布式系统中,集群管理依赖zookeeper的watcher机制。由于watcher对于节点事件(另一种是连接事件)是一次性的,即一旦触发就失效,若想再次获取相应zk路径上的事件,需要再次设置watcher。如果zk路径在两次watcher之间发生了改变,client端是无法感知到的,这就是所谓zk事件丢失。
思路:我们使用zk是为了处理某种问题,解决丢事件的问题,不必非得严格使用watcher,只要能解决实际问题即可;所以一种可行的方法是:
1、采取削弱client端对于zookeeper服务的依赖性,将client端对zk事件的处理退化为轮询,zk事件作为触发轮询的条件:
2、先设置watcher,后修改数据(创建路径)等;
伪代码如下:
package main
func zk_watch(conn zk.Conn, path string) {
// a loop
go func() {
var exists bool
var ch <-chan zk.Event
exists,_,ch, err = conn.ExistsW(path) // OR conn.GetW(), and others
if err == nil {
go func() {
/* do something */
}()
e := <-ch
} else {
/* handle error */
}
}
}
func main() {
conn,_,err := zk.Connect(host, time, option)
zk_watch(conn, path) // set watcher first
zk.Create(path, data, flag, acl)
/* do other things */
}
参考:
http://blog.chinaunix.net/uid-451-id-3228557.html