提一个问题先

  zxid有64位,分成两部分:

  高32位是Leader的epoch:选举时钟,每次选出新的Leader,epoch累加1

  低32位是在这轮epoch内的事务id:对于用户的每一次更新操作集群都会累加1。

  这么设计会存在什么问题?

  Zookeeper 的事务 ID 有可能会超过 32 位。

  epoch增长非常慢,超过32位需要非常久的时间,几乎可以忽略这个问题,但是事务 ID 似乎不行。我们来算下。

  如果我们每秒钟操作1000次 Zookeeper ,即 1k/s ops,那么

  2^32/(86400∗1000)≈49.7

  49.7天后,事务 ID 就将溢出,那溢出会发生什么,看代码:

 

  /**

  * create a proposal and send it out to all the members

  *

  * @param request

  * @return the proposal that is queued to send to all the members

  */

  public Proposal propose(Request request) throws XidRolloverException { /**

  * Address the rollover issue. All lower 32bits set indicate a new leader

  * election. Force a re-election instead. See ZOOKEEPER-1277

  */

  if ((request.zxid 0xffffffffffL) == 0xffffffffffL) {

  String msg = zxid lower 32 bits have rolled over, forcing re-election, and therefore new epoch start;

  shutdown(msg); throw new XidRolloverException(msg);

  }

  从上面的代码可以看到,

  Zookeeper 的 Leader 节点会throw new XidRolloverException(msg) 强制进行 re-election重新选举,

  即服务会停止一段时间,在一些场景下,这种情况过于频繁是不能容忍的,那我们来看看如何解决。

  如何解决?

  上面说了epoch增长速度慢到可以忽略它溢出的问题,那么可以重新设计 ZXID,

  设计成高 24 位用于 epoch,低 40 位用于 事务 ID 增长。

  我们再来算一下:

  2^40/(86400∗1000)≈12725.8即12725.8/365≈34.9年

  1k/s ops 的情况下, 34.9 年之后才会进行一次强制选举。

  设想不错,可以解决我们的问题,那我们继续。

  还有一个担心

  从操作系统的底层来说,对于32位操作系统,单次操作能处理的最长长度为32bit,而long类型8字节64bit,所以对long的读写都要两条指令才能完成(即每次读写64bit中的32bit)。

  为什么说这个,因为也许有人会把这个和 ZXID 的设计联想起来,上面的ZOOKEEPER-2784里面也提到了这个问题。

  However, i thought the ZXID islongtype, reading and writing the long type (anddoubletype the same) in JVM, is divided into high 32bit and low 32bit part of the operation, and because theZXIDvariable is not modified withvolatileand is not boxed for the corresponding reference type (Long/Double), so it belongs to [non-atomic operation]

  我大概翻译一下:

  ZXID 是 long 类型,32 bit 的 JVM 在对 long 读写时(和 double 类型一样),是分为高 32 位和 低 32 位两部分进行操作的,由于 ZXID 变量没有用 volatile 修饰,且也没有装箱为对应的引用类型(Long / Double),属于非原子操作。

  这位老哥担心对 ZXID 重新设计时把高 32 位和 低 32 位改成高 24 位和 低 40 位,可能会存在并发的问题。

  会不会有这个问题,我们先来看看源码:

  Iteratoriterator = servers.iterator(); long zxid = Long.valueOf(m.group(2)); int count = (int)zxid;// 0xFFFFFFFFL;

  int epoch = (int)Long.rotateRight(zxid, 32);// 32;

  注意这个 0xFFFFFFFFL,实际上后面的代码还有很多这种按位与的操作,就不贴出来了。

  翻了这一块的源码就可以知道,这个担心是多余的,关于ZXID的所有操作都是位操作而不是“=”的赋值操作,它不会造成JVM级别的并发问题。

  如何修改

  接下来我们就用源码中“位与”的方式,把 32 为改成 40 位。

  即:zxid按位于()0xffffffffffL(40位)获得zxid的后40位。

  注意要把count之前的int类型改为long类型,因为int为32bit,long为64bit,此时count有40位所以换成long。

  Iteratoriterator = servers.iterator(); long zxid = Long.valueOf(m.group(2)); // int count = (int)zxid;// 0xFFFFFFFFL;

  // int epoch = (int)Long.rotateRight(zxid, 32);// 32;

  long count = zxid 0xffffffffffL; int epoch = (int)Long.rotateRight(zxid, 40);// 40;

  后面还有多处类似的地方要修改,就不一一列出来了,

zookeeper篇-如何修改源码的更多相关文章

  1. zookeeper-如何修改源码-《每日五分钟搞定大数据》

    本篇文章仅仅是起一个抛砖迎玉的作用,举一个如何修改源码的例子.文章的灵感来自 ZOOKEEPER-2784. 提一个问题先 之前的文章讲过zxid的设计,我们先复习下: zxid有64位,分成两部分: ...

  2. openvswitch2.11.0修改源码后重新编译(2)

    一:前提 已经正常安装了SDN环境(mininet和openswitch2.11.0和Ryu) 使用前面教程安装环境SDN实验---使用git安装Mininet (一)测试ovs是否正常使用 1.ry ...

  3. WordPress安装篇(5):源码编译安装LNMP并部署WordPress

    与YUM方式安装相比,源码编译安装方式更灵活,安装过程中能自定义功能和参数,特别是在批量部署服务器又要求软件版本及配置一致时,源码编译安装的优势很明显.本文介绍如何通过源码编译方式安装Nginx1.1 ...

  4. Sentinel控制台1.8.3修改源码,修改配置后推送到Nacos

    目录 1. 接着上一篇 2. 思路 3. 下载Sentinel源码 4. 看Gateway里面读取的配置信息 5. 修改Sentinel控制台源码 6. 熔断规则测试 7. 限流规则测试 8. 打包使 ...

  5. Android5.1.1 - APK签名校验分析和修改源码绕过签名校验

    Android5.1.1 - APK签名校验分析和修改源码绕过签名校验 作者:寻禹@阿里聚安全 APK签名校验分析 找到PackageParser类,该类在文件“frameworks/base/cor ...

  6. 75篇关于Tomcat源码和机制的文章

    75篇关于Tomcat源码和机制的文章 标签: tomcat源码机制 2016-12-30 16:00 10083人阅读 评论(1) 收藏 举报  分类: tomcat内核(82)  版权声明:本文为 ...

  7. 设置ZooKeeper服务器地址列表源码解析及扩展

    设置ZooKeeper服务器地址列表源码解析及扩展 ZooKeeper zooKeeper = new ZooKeeper("192.168.109.130:2181",SESSI ...

  8. Windows7 64位环境6sv2.1大气传输模型修改源码添加国产高分卫星GF-1 GF-2光谱响应支持

    下面开始添加国产卫星光谱响应的支持: 以下主要参考文章“6S大气传输模型修改源码添加.自定义卫星光谱响应(以HJ-1B CCD为例)”网址:http://blog.csdn.net/sam92/art ...

  9. element-ui 修改源码实践 --tranfer

    1.element-ui 地址:https://github.com/ElemeFE/element 2.修改elelment-ui版本:2.2.2(请选择和项目相对应的版本) 3.修改内容:穿梭框组 ...

随机推荐

  1. eigen 笔记1

    c++ 的 eigen 类似于 python 的 numpy, 还有一个类似的库是 Armadillo, 当然还有 opencv. Armadillo 与 matlab 在函数名称上更接近, 但是 T ...

  2. qt用mingw编译时报错 multiple definition of

    网上相关回答不少,但过于简单,这里做一下记录. qt用mingw编译程序时报“multiple definition of …”这个错误,错误信息大概是如下图所示: 1 2 3 首先,检查自己的程序是 ...

  3. Qt 布局管理器

    在一个颜值当道的今天,无论买衣服,买车还是追星,颜值的高低已经变成了大家最看重的(不管男性女性都一样,千万别和我说你不是):而对于程序猿来说,开发一款软件,不再只注重逻辑和稳定性,美观和用户友好性也是 ...

  4. 有意思的JSON.parse()、JSON.stringify()

    前言 现在JSON格式在web开发中非常重要,特别是在使用ajax开发项目的过程中,经常需要将后端响应的JSON格式的字符串返回到前端,前端解析成JS对象值(JSON 对象),再对页面进行渲染. 在数 ...

  5. XML—代码—DOM4J解析

    什么是xml: 众所周知,xml常用语数据存储和传输,文件后缀为 .xml: 它是可扩展标记语言(Extensible Markup Language,简称XML),是一种标记语言. 如何定义这些标记 ...

  6. webstorm使用心得

    收藏夹功能:当工程目录很庞大时,有些子目录很经常打开,但层级又很深,这时候可以把目录添加到收藏夹里面,添加成功后,左侧有个“Favorites”菜单 面包屑导航:除了左侧的工程页面,可以选择目录之外, ...

  7. 隐马尔科夫模型(HMM)学习笔记二

    这里接着学习笔记一中的问题2,说实话问题2中的Baum-Welch算法编程时矩阵转换有点烧脑,开始编写一直不对(编程还不熟练hh),后面在纸上仔细推了一遍,由特例慢慢改写才运行成功,所以代码里面好多处 ...

  8. Python tricks(7) -- new-style class的__slots__属性

    __slots__是在python 2.2开始引入的一个新特性, 我们来看一下官方给出的解释. This class variable can be assigned a string, iterab ...

  9. Python Web学习笔记之Python多线程和多进程、协程入门

    进程和线程究竟是什么?如何使用进程和线程?什么场景下需要使用进程和线程?协程又是什么?协程和线程的关系和区别有哪些? 程序切换-CPU时间的分配 首先,我们的任何一个程序都需要运行在一个操作系统中,如 ...

  10. COOKIE与SESSION、Django的用户认证、From表单

    一.COOKIE 与 SESSION 1.简介 1.cookie不属于http协议范围,由于http协议无法保持状态,但实际情况,我们却又需要“保持状态”,因此cookie就是在这样一个场景下诞生. ...