一、前言

  前面分析了LeaderZooKeeperServer,接着分析FollowerZooKeeperServer。

二、FollowerZooKeeperServer源码分析

  2.1 类的继承关系  

public class FollowerZooKeeperServer extends LearnerZooKeeperServer {}

  说明:其继承LearnerZooKeeperServer抽象类,角色为Follower。其请求处理链为FollowerRequestProcessor -> CommitProcessor -> FinalRequestProcessor。

  2.2 类的属性  

public class FollowerZooKeeperServer extends LearnerZooKeeperServer {
private static final Logger LOG =
LoggerFactory.getLogger(FollowerZooKeeperServer.class);
// 提交请求处理器
CommitProcessor commitProcessor; // 同步请求处理器
SyncRequestProcessor syncProcessor; /*
* Pending sync requests
*/
// 待同步请求
ConcurrentLinkedQueue<Request> pendingSyncs; // 待处理的事务请求
LinkedBlockingQueue<Request> pendingTxns = new LinkedBlockingQueue<Request>();
}

  说明:FollowerZooKeeperServer中维护着提交请求处理器和同步请求处理器,并且维护了所有待同步请求队列和待处理的事务请求队列。

  2.3 类的构造函数  

    FollowerZooKeeperServer(FileTxnSnapLog logFactory,QuorumPeer self,
DataTreeBuilder treeBuilder, ZKDatabase zkDb) throws IOException {
super(logFactory, self.tickTime, self.minSessionTimeout,
self.maxSessionTimeout, treeBuilder, zkDb, self);
// 初始化pendingSyncs
this.pendingSyncs = new ConcurrentLinkedQueue<Request>();
}

  说明:其首先调用父类的构造函数,然后初始化pendingSyncs为空队列。

  2.4 核心函数分析

  1. logRequest函数  

    public void logRequest(TxnHeader hdr, Record txn) {
// 创建请求
Request request = new Request(null, hdr.getClientId(), hdr.getCxid(),
hdr.getType(), null, null);
// 赋值请求头、事务体、zxid
request.hdr = hdr;
request.txn = txn;
request.zxid = hdr.getZxid();
if ((request.zxid & 0xffffffffL) != 0) { // zxid不为0,表示本服务器已经处理过请求
// 则需要将该请求放入pendingTxns中
pendingTxns.add(request);
}
// 使用SyncRequestProcessor处理请求(其会将请求放在队列中,异步进行处理)
syncProcessor.processRequest(request);
}

  说明:该函数将请求进行记录(放入到对应的队列中),等待处理。

  2. commit函数 

    public void commit(long zxid) {
if (pendingTxns.size() == 0) { // 没有还在等待处理的事务
LOG.warn("Committing " + Long.toHexString(zxid)
+ " without seeing txn");
return;
}
// 队首元素的zxid
long firstElementZxid = pendingTxns.element().zxid;
if (firstElementZxid != zxid) { // 如果队首元素的zxid不等于需要提交的zxid,则退出程序
LOG.error("Committing zxid 0x" + Long.toHexString(zxid)
+ " but next pending txn 0x"
+ Long.toHexString(firstElementZxid));
System.exit(12);
}
// 从待处理事务请求队列中移除队首请求
Request request = pendingTxns.remove();
// 提交该请求
commitProcessor.commit(request);
}

  说明:该函数会提交zxid对应的请求(pendingTxns的队首元素),其首先会判断队首请求对应的zxid是否为传入的zxid,然后再进行移除和提交(放在committedRequests队列中)。

  3. sync函数  

    synchronized public void sync(){
if(pendingSyncs.size() ==0){ // 没有需要同步的请求
LOG.warn("Not expecting a sync.");
return;
}
// 从待同步队列中移除队首请求
Request r = pendingSyncs.remove();
// 提交该请求
commitProcessor.commit(r);
}

  说明:该函数会将待同步请求队列中的元素进行提交,也是将该请求放入committedRequests队列中。

三、总结

  本篇学习了FollowerZooKeeperServer的源码,其核心是对待同步请求和待处理事务请求交由不同的请求处理器进行处理。也谢谢各位园友的观看~

【Zookeeper】源码分析之服务器(四)之FollowerZooKeeperServer的更多相关文章

  1. zookeeper源码分析之四服务端(单机)处理请求流程

    上文: zookeeper源码分析之一服务端启动过程 中,我们介绍了zookeeper服务器的启动过程,其中单机是ZookeeperServer启动,集群使用QuorumPeer启动,那么这次我们分析 ...

  2. zookeeper源码分析之三客户端发送请求流程

    znode 可以被监控,包括这个目录节点中存储的数据的修改,子节点目录的变化等,一旦变化可以通知设置监控的客户端,这个功能是zookeeper对于应用最重要的特性,通过这个特性可以实现的功能包括配置的 ...

  3. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

  4. Zookeeper 源码分析-启动

    Zookeeper 源码分析-启动 博客分类: Zookeeper   本文主要介绍了zookeeper启动的过程 运行zkServer.sh start命令可以启动zookeeper.入口的main ...

  5. 手机自动化测试:appium源码分析之bootstrap四

    手机自动化测试:appium源码分析之bootstrap四   Orientation是调整屏幕方向的操作 package io.appium.android.bootstrap.handler; i ...

  6. 【Zookeeper】源码分析之服务器(四)

    一.前言 前面分析了LeaderZooKeeperServer,接着分析FollowerZooKeeperServer. 二.FollowerZooKeeperServer源码分析 2.1 类的继承关 ...

  7. 【Zookeeper】源码分析之服务器(二)

    一.前言 前面阐述了服务器的总体框架,下面来分析服务器的所有父类ZooKeeperServer. 二.ZooKeeperServer源码分析 2.1 类的继承关系 public class ZooKe ...

  8. 【Zookeeper】源码分析之服务器(二)之ZooKeeperServer

    一.前言 前面阐述了服务器的总体框架,下面来分析服务器的所有父类ZooKeeperServer. 二.ZooKeeperServer源码分析 2.1 类的继承关系 public class ZooKe ...

  9. 【Zookeeper】源码分析之服务器(五)之ObserverZooKeeperServer

    一.前言 前面分析了FollowerZooKeeperServer,接着分析ObserverZooKeeperServer. 二.ObserverZooKeeperServer源码分析 2.1 类的继 ...

随机推荐

  1. python全栈开发day12-函数的有用信息、带参数的装饰器、多个装饰器装饰一个函数、global和nonlocal的进一步解析和总结

    1.上周回顾 1).函数名的应用 直接打印函数名,是函数的地址 变量 函数的参数 函数的返回值 可以当容器类数据类型的元素 2).闭包 内层函数对外层函数的非全局变量的引用,就是闭包. 并返回内部函数 ...

  2. Ubuntu 下wifi掉线

    http://blog.csdn.net/sean_xyz/article/details/51141063

  3. Redis持久化(persistence)

    Redis 持久化 Redis 提供了多种不同级别的持久化方式: RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照(point-in-time snapshot). AOF 持久化记录服务器 ...

  4. 你有哪些想要分享的 PyCharm 使用技巧?

    作者:Light Lin链接:https://www.zhihu.com/question/37787004/answer/75269463来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...

  5. SSL/TLS中间人攻击

    准备:kali.xp kali ip:192.168.14.157 目标ip:192.168.14.158 目标网关:192.168.14.2 使用工具:ettercap.sslstrip.arpsp ...

  6. python数据分析之pandas数据选取:df[] df.loc[] df.iloc[] df.ix[] df.at[] df.iat[]

    1 引言 Pandas是作为Python数据分析著名的工具包,提供了多种数据选取的方法,方便实用.本文主要介绍Pandas的几种数据选取的方法. Pandas中,数据主要保存为Dataframe和Se ...

  7. Linux文本处理三剑客之grep

    简介 grep命令,用于在一个文本文件中或者从STDIN中,根据用户给出的模式(pattern)过滤出所需要的信息. grep以及三剑客中的另外两个工具sed和awk都是基于行处理的,它们会一行行读入 ...

  8. js获取当前用户IP地址和城市

    引用下面的js: <script src="http://pv.sohu.com/cityjson?ie=utf-8"></script> 直接获取IP和城 ...

  9. IdentityServer4-介绍

    一.总体介绍 大多数现代应用或多或少是这样的: 通常,每个层(前端.中间层和后端)都必须保护资源并实现身份验证和/或授权——通常针对相同的用户存储. 将这些基本的安全功能外包给安全令牌服务,可以防止在 ...

  10. C# DataTable分页函数

    /// <summary> /// 对DataTable进行分页,起始页为1 /// </summary> /// <param name="dt"& ...