Zookeeper中snapshot过程与session简介

8. snapshot原理

    ZK Snapshot主要意义就是将当前Database + Memory中数据的状态,直接序列化到文件,以方便在故障时可以迅速恢复.snapshot是fuzzy的(非严格意义的snapshot),snapshot所涉及到的类有SyncRequestProcessor(同步请求处理器,处理请求的log同步到disk)/ZKDatabase(ZK内存数据库)/TxnLog(事物日志)/SnapLog等。
    Snapshot的流程比较简单,源码(SyncRequestProcessor)复述如下:

  • 对于任何变更操作,首先添加到请求队列中,并记录txnLog,记录到txnLog的目的,就是防止物理机器崩溃但数据尚未持久化所带来的一致性问题,同时txnLog也是数据恢复/校验Database数据是否持久成功的标准.
  • 从请求队列中,获取队列头部的请求操作(如果队列为空,将阻塞),将"请求"append进入txn log,logCount计数器+1;如果logCount计数器达到snapCount/2 + random(snapCount/2),将依次触发2个操作:首先关闭当前txn log,并新建一个tnx log来存储当前请求日志;然后对ZKDatabase进行snapshot(zookperServer.takeSnapshot()),snapshot是一个异步的过程,也是非常耗时的,ZK将开启一个新的独立线程来进行;此线程将会根据“snapshot.zid”的格式新建一个snapshot文件,并依次序列化sessionMap,ACL列表,DataTree。[即把Database中的数据全部序列化到snapshot文件中];之所以ZK 的snapshot是fuzzy的原因,它并没有遵循文件系统或类文件系统的snapshot规范,没有在snapshot过程中对zkDatabase或者说update请求进行阻塞,所以此snapshot文件中仍然会包含zid(此zid即为snapshot时Database中所持有的最大的zid)之后的数据变更,就像在给人拍照时,“人”并没有“暂停”活动,所以图片是“fuzzy”的。当然,这并不会对snapshot文件的恢复带来任何危害。这一切需要归咎与zk的数据库为内存数据库,而非文件数据库。
  • logCount置为0,“处理器链”将会继续传递,在FinalRequestProcessor将会把update请求变更位ZKDatabase数据。logCount是触发snapshot的开关,当变更操作的个数达到阀值,将会触发snapshot.
  • 循环1)

    注意:ZK是基于JVM,且为高内存消耗进程,所以对JVM的heap大小有一定的要求,如果heap过小,将会造成内存数据的多次swap,带来性能隐患。在高性能高可用cluster环境中,建议将ZK server部署在单独物理服务器上。

9. ZK Session:[Session原理详解]


Zookeeper中snapshot过程与session简介
 

    Zk客户端通过使用语言绑定(language binding)创建一个service的handle,来和zk service建立session。一旦创建,此handle初始为CONNECTING状态,然后client将会尝试与zk service中的一台server建立链接,链接成功后,状态将会被转换为CONNECTED。在一般情况下,session会是这两个状态中的一种。不过,当发生不可恢复时,例如session过期或者验证失败,或者应用明确的关闭了handle,那么此session的handle将会被变更为CLOSED状态。下图为session状态转换(来自apache zookeeper官网)
当client从zk service中获取一个handle(句柄)之后,zk将会为client创建一个session,sessionID为一个64位的数字。如果client链接到了其他的server上,它(client)将会把session id作为“握手”链接的一部分发送给server。因为安全的因素,server还为session id创建了一个password,以便任何ZK server都能够验证。当session创建成功后,session id和password都将会发送给client。无论client和哪个server建立链接,它都必须将session id和password一同发送给需要建立链接的server。
    当client连接失效后,它将会检索指定的server列表,并与其中一个server重新建立链接,session的状态被再次转换为CONNECTED(在session timeout有效期内),或者将会被转换成“EXPIRED”状态(session timeout之后,建立了链接)。不建议在链接失效后,创建新的session(Zookeeper实例),ZK client将会为你处理重链接。此外,ZK内置的一些机制来处理类似“羊群效应”等等。当client被通知session过期,只需要创建一个新的session即可。
    A)’CONNECTED‘:session已经被创建,并且client正在和cluster通信。
    B)Client的信息将被Cluster所维持,并成为Cluster环境数据的一部分.
    C)’DISCONNECTED‘:client失去server的链接
    D)...一段时间后,即在“timeout”期间之后,cluster使session过期(移除session句柄),此时客户端并不能获取任何信息和通知,因为它仍没有和cluster server建立链接
    E)...一段时候后,client再此和server建立了链接,连接时将会把session id一并发送给server.
    F)'EXPIRED':如果session过期,client此时获取一个“过期”的通知。(session 过期后,ZK句柄的所有数据需要重建,及需要重新实例化zookeeper)

    Client与Server持续通讯时,也意味着Session是"活跃"的(sessionId将会伴随每次请求交付给server),如果session空闲一段时间,这将会导致过期,所以client会发送一种PING类型的请求来保持session的alive,PING请求不仅可以让server知道client仍然存活,而且它也能够验证当前zk server是否alive。

    关于SessionMovedException:这是个内部异常,客户端将不会看到它。发生的原因是,一个请求的发送给server,但是因为网络的原因,此请求packet被延迟了,所以client链接超时后重新链接了其他的server,不过被延迟的packet最终到达了server,不过此旧server检测到此session已经被“moved”(即client所对应的session的"维护者"变成了其他server),就关闭了链接。所以客户端是无法获得此异常,因为旧链接已经被关闭而无法读取数据。。
(源码所涉及到的类: Zookeeper(单机模式下)/LeaderZookeeperServer(分布式模式下),SendThread,SessionTrackImpl.run)大概意思:zookeeperServer启动后(如果是分布式模式,将有LeaderZookeeper负责Session过期控制),都会创建一个SessionTrackImpl,tracker就是跟踪session的,其中一个属性为sessionSets,它是一个map,保持了tick(过期时间)与session,此tick为下一次过期的时间点(计算很有意思,是(当前系统时间/配置文件中的tick + 1)* tick),此时间点为tick间隔的整数倍,并且会不断被延迟。sessionTrack本身就是个线程,此线程会不断轮询,删除那些在过期时间点上的session,删除后,并有leader向集群中其他Followers发送closeSession请求。。线程执行时会检测tick和当前时间的关系,如果大于当前时间,就wait,直到时间点,执行之后,从新计算tick。

相关推荐