ZK的几个常用方式

1、实现锁

ZK的每一个存在一个顺序节点,在你创建顺序节点时,ZK会自动添加一个自增的编号上去,编号最大是INT_MAX(2147483647 ),如果超出就走溢出,变成负数。

每个获取锁的客户端,在父节点下新建一个自己顺序节点,然后再获取父节点的所有孩子节点,并且设置Watch,观看孩子节点的变化,查看当前第一个节点是否是自己(根据ZK添加的自增编号从小到大排序)。

1、如果是自己即获取到锁,执行业务,然后释放锁。

2、如果不是自己,即未获取到锁,进行thread.wait(),或者再去获取都行。如果wait(),必须在获取孩子节点时设置watch,并且得到孩子节点变化进行notify()。

2、实现Barrier

Barrier含义是等待内部事件,然后同时开始,比如等有5人后就开始干活。

实现过程:

1、参与Barrier的选定一个父节点,然后在父节点上设置child类型watch(观察子节点的变化)。

2、在进入barrier的函数里面,设置自己的子节点,获取当前父节点的孩子节点个数,如果等于Barrier size,那就是人到齐了,进行业务处理,业务处理完后,把子节点delete掉。

3、如果不够,则进入thread.wait()。

4、在zk的事件回调函数,调用thread.notify()函数,注意,需要判断EventType。

异常情况处理。

客户端连接中断,如果出现这个情况,再次执行流程,如果创建的是临时节点,需要检查节点是否存在,如果不存在,需要重建。如果重连后不处理,可能导致Barrier永远无法满足。

3、实现Queue

实现原理和实现锁类似。使用顺序节点,把Queue的数据放在Data内部。

4、实现2PC

2PC角色分为俩个,协调者和参与者。

1、协调者创建事务节点 /app/Tx

2、协调者给每个参与者在/app/Tx下创建子节点,比如/app/Tx/s_i,协调者创建的孩子节点让数据域是空的。

3、参与者读取所有孩子节点,然后在每个孩子节点上设置watch。

4、参与者处理完事务后在自己的节点的内写commit或abort。

5、参与者写完后,其他节点就会收到通知,这样参与者就能收到所有决定,决定是abort还是commit。

6、2PC过程完毕,协调者删除/app/Tx。

实现的缺点:

1:消息复杂,需要O(n²)。

2:无法通过创建临时节点来检查到参与者故障。

解决方法:

1:事务节点的改变事件仅通知给协调者,然后协调者通知参与者是应该commit还是abort,但是这样会很慢,因为所有的消息全部由协调者处理。

2:第二个问题,由协调者者生成每个事务节点名字,发送给参与者,由参与者自己创建临时节点。

异常情况处理:

正常的2PC过程,

第一步:协调者发起,首先各个事务节点进入prepare过程。

第二步:事务节点进行事务处理,然后返回给协调者结果。

第三步:协调者根据各个事务节点的结果,决定让各个事务节点是commit/abort。

在用ZK实现时,不存在prepare过程。

1.如果协调者在事务处理过程中宕机,重启后,需要询问事务的结果,然后决定是否应该进行事务重做。

2:此时协调者是弱关系,如果宕机,只要询问最后的结果就行。

5、实现选举

实现选举也很简单,每个参与选举的客户端都对应ZK的一个节点,然后其他流程和实现锁的方式一致,只是,当前是自己时,一直不删除节点就行了。

具体可以参考我的代码,实现很粗略:

https://github.com/tangzhe7/zklock

curator框架的sample。

https://github.com/apache/curator/tree/master/curator-examples

声明:该文章系转载,转载该文章的目的在于更广泛的传递信息,并不代表本网站赞同其观点,文章内容仅供参考。

本站是一个个人学习和交流平台,网站上部分文章为网站管理员和网友从相关媒体转载而来,并不用于任何商业目的,内容为作者个人观点, 并不代表本网站赞同其观点和对其真实性负责。

我们已经尽可能的对作者和来源进行了通告,但是可能由于能力有限或疏忽,导致作者和来源有误,亦可能您并不期望您的作品在我们的网站上发布。我们为这些问题向您致歉,如果您在我站上发现此类问题,请及时联系我们,我们将根据您的要求,立即更正或者删除有关内容。本站拥有对此声明的最终解释权。