• zookeeper中Watcher和Notifications


    问题导读:
    1.zookeeper观察者什么时候调用?
    2.传统远程轮询服务存在什么问题?
    3.zk中回调服务的机制是什么?
    4.zk中watcher为什么不永久注册?
    5.什么是znode?











    在阅读之前首先明确个概念:
    1.什么是znode?


    2.什么是客户端?

    我们使用znode这个术语来表示ZooKeeper的数据节点

    znode维持一个stat结构,它包含数据变化的版本号、ACL变化和时间戳,以允许cache校验和协调化的更新。每当znode的数据变化时,版本号将增加。一个客户端收到数据时,它也会收到数据的版本号。

    保存在每个znode中的数据都是自动读写的。读操作获取znode的所有数据,写操作替换掉znode的所有数据。每个节点有一个访问控制表(ACL)来限制谁能做哪些操作。
    Zookeeper中的角色主要有以下三类,如下表所示:
    <ignore_js_op> 
    系统模型如图所示:
    <ignore_js_op> 





    传统轮询远程service服务
    传统远程的service往往是这样服务的,服务提供者在远程service注册自己的服务,服务调用者不断去远程service轮询看看是否服务提供者有没有提供服务或者更新服务。所以有弊端,就是延时比较高,而且因为很多不必要的空轮询带来高的负载和网络损耗,这种模式到zk里面就应该是这样。


    <ignore_js_op> 



    zk中异步回调服务

    zk实际上的实现是异步回调来代替polling,引入一种机制是event inotifications:客户端首先注册到zk service从而可以接收znode的改变事件,也就是说一旦watch的znode变更了,客户端就会得到相应的通知,然后处理自己的业务逻辑。

    <ignore_js_op> 


    • zk客户端可以通过exists,getChildren,getData可以注册观察者,观察者说白了就是指定一个callback
    • 那么观察者什么时候调用呢?一旦监听的znode变化了,zk service就会发送对应znode路径给客户端,客户端调用相应的之前注册的回掉函数处理。对于节点的create,delete,setData都会触发观察者,也就是这个callback()函数。


    服务端只存储事件的信息,客户端存储事件的信息和Watcher的执行逻辑。客户端在注册watcher的时候,在客户端本地会维持对应znode path和callback()的对应关系。在服务端会维护对应连接session以及znode path和事件类型。服务端触发了对应的事件类型后,会发送给客户端事件类型和znode path,在客户端会根据映射关系调用相应的callback(),接下来的业务逻辑都是在客户端实现的。

    zk中watcher单次触发问题

    zk中的Watch是一次触发的,一次变更只会触发一个通知,要想下次还得到通知,就需要重新注册。为什么不是永久注册Watcher呢?这主要是考虑到性能上面的影响吧。看下面的情况

    • Client C1对于znode /Task 设置了一个watcher
    • Client C2来到然后对 /Task 增加znode
    • Client C1接收到了notifications,得知监控的znode变化了
    • Client C1在处理这个notifications,这时候Client C3又增加 /task 一个znode


    在步骤3的时候C1已经触发了一次watcher,步骤四的时候没有watcher了,除非重新设置watcher,所以这个过过程中就会丢失一个notifications,这就是涉及到了CAP原理了。zookeeper只能保证最终一致性,不能保证强一致性,但是因为zk保证了顺序一致性,所以就能确保最终一致性。

    • 强一致性:分布式系统里面一个数据变更后,访问任一个服务都可以得到最新的数据
    • 弱一致性:一个数据变更后,其中部分服务可以得到最新数据,部分服务不能
    • 最终一致性:在更新某个数据后,可能在开始的时候得不到最新的数据,但是最终是可以呈现最新的数据
    • 顺序一致性:更新N份数据,能保证是服务是按照N份数据顺序更新提供服务的。

    其实对于上面的case也是有办法解决的,具体就是每次在注册watcher之后都getData,保证数据版本是最新的,但相比较传统的polling优势还是很明显的。

    zk中Versions

    每个znode一旦数据变化,都会有一个递增的版本号,在zk API执行的时候都需要指定版本号,客户端提供的版本号只有和服务端匹配了才能进行znode操作。在多个客户端都要操作同一个znode的时候版本号就很重要了。看下面的情况。

    • 比如Client C1写了一个znode /Nginx/conf的数据,写了一些配置信息,这时候/Nginx/conf版本号就从version1变成version2
    • 在上面的同时,Client C2也想写/Nginx/conf,因为C2的客户端版本还是version1,而服务端已经是version2了,此刻就会冲突,这个操作就会以失败告终。所以必须要先更新C2上到version2,然后再提交操作。
    zk上更新version2到version3,C2本地更新至version3



    <ignore_js_op>




  • 相关阅读:
    VS2010 自动跳过代码现象
    Reverse Linked List II 【纠结逆序!!!】
    Intersection of Two Linked Lists
    Linked List Cycle II
    Remove Nth Node From End of List 【另一个技巧,指针的指针】
    Swap Nodes in Pairs
    Merge Two Sorted Lists
    Remove Duplicates from Sorted List
    Linked List Cycle
    Dungeon Game
  • 原文地址:https://www.cnblogs.com/likehua/p/4060324.html
Copyright © 2020-2023  润新知