前言:

RDS系统致力于MySQL数据的高可用,高可靠,高性能以及在线扩展功能,实现这些特性的主要逻辑功能都运行在管理服务器上,一旦管理服务器宕机,数据库的在线扩展功能/备份功能/故障恢复功能等都无从谈起。然而,之前RDS系统管理服务器却是单点服务,为了保证整个系统的稳定性,管理服务器需要实现高可用,结合当前主流的高可用方案,决定使用Zookeeper来实现服务的高可用。

基本设计方案原理:

如下图所示,管理服务器A B C会在zk的root节点上注册临时序列节点/root/manager000000001  /root/manager000000002 /root/manager0000000003,序列最小的节点会被选为leader对外提供服务,其他节点作为热备节点随时准备升为leader。在此图中,A是leader,B C是standby。一旦A服务器因为某些原因宕机,zk就会将该服务器注册的临时节点移除掉,然后通知所有其他节点B C,B C会选出序列号最小的节点作为新的leader对外提供服务,此时B就会被选为新主。

血案现场:

会有这么一种比较特殊的场景需要考虑,比如当前leader是A BC都是备机。假如A和zk集群之间的网络出现了异常,A会收到一个连接状态被持久化为Disconnected的event,但是ZK Server并没有在这时移除A注册的临时节点,所以理论上A还是leader直至session timeout,session timeout后zk会将A注册的临时节点移除掉,然后通知B C选出新的leader,显而易见,B因为序列号小会成为新的leader。但是问题来了,session timeout的时候A的客户端并没有接收到任何notification,换句话说,它依然会认为自己是leader,这个时候就出现了这样的场景,A认为自己是leader,而B同样会认为自己是leader,即同时出现两个leader对外提供服务的情况。这很显然是不合理的,但如何深入地理解并解决这个问题呢?

个人认为理解并解决这个问题需要理解下面三个子问题:

1. 理解Zookeeper中Session的含义以及Connection Loss和Session Expired的关系

2. 理解Zookeeper中Session为什么由Server维护,而不由Client维护

3. 理解作为leader的A在整个流程中应该如何转变自己的角色,来避免脑裂

对zookeeper中Connection Loss和Session Expired的理解

Session是指当Client创建一个同Server的连接时产生的会话。连接Connected之后Session状态就开启,Zookeeper服务器和Client采用长连接方式(Client会不停地向Server发送心跳)保证session在不出现网络问题、服务器宕机或Client宕机情况下可以一直存在。因此,在正常情况下,session会一直有效,并且ZK集群上所有机器都会保存这个Session信息。

在ZK中,很多数据和状态都是和会话绑定的,一旦会话失效,那么ZK就开始清除和这个会话有关的信息,包括这个会话创建的临时节点和注册的所有Watcher。

一旦网络连接因为某种原因断开或者zk集群发生宕机,ZK Client会马上捕获到这个异常,封装为一个ConnectionLoss的事件,然后启动自动重连机制在地址列表中选择新的地址进行重连。重连会有三种结果:

(1)在session timeout时间内重连成功,client会重新收到一个syncconnected的event,并将连接重新持久化为connected状态

(2)超过session timeout时间段后重连成功,client会收到一个expired的event,并将连接持久化为closed状态

(3)一直重连不上,client将不会收到任何event

很显然,无论重连成功与否,在session timeout那个重要的时间点,ZK Client是接收不到任何ZK Server清理临时节点的信息的。这也就导致ZK会通知了B C节点A已经不再是Leader,A自身却没有接收到这样的信息,依旧对外提供服务,进而产生脑裂的问题。

Zookeeper中Session为什么由Server维护,而不由Client维护

可能很多朋友看了上面的讨论就会想为什么ZK Client不维护Session信息,如果这样做了,ZK Client就会在Session Timeout时得到相应的通知。

好,现在假如这样实现了,看看会发生什么。设想有这么一种真实场景,某个连接的Session Timeout是15s,ZK集群因为未知原因发生宕机,5min之后集群恢复成功。在Session Timeout时,ZK Client确实可以知道Session失效,然后做降主操作,但是ZK Server却不知道Session已经失效,也就不会通知其他节点选出新的Leader,此时整个系统实际上处于没有Leader的状态。即使5min之后重连成功,因为旧Session对应的临时节点没有被清理且序号最小,ZK依然会认为Leader是该临时节点,而实际上该临时节点对应不到任何的ZK Client,所以这种情况下系统依然选不出Leader。

可见,如果由Client维护Session,在某些场景下(网络异常或者集群宕机时间超过Session Timeout),由于逻辑问题根本选不出Leader。

因此这种方案是不可行的。

那能不能从应用层面避免脑裂问题呢?带着问题进入下个部分。

避免脑裂问题:作为leader的A在整个流程中应该如何转变自己的角色

因为ZK本身的设计使得这种场景下没有一个完美的解决方案,可以考虑采用退化的方案进行处理。

A在接收到DisConnected事件后就降主,不对外提供服务。然后等待接下来的发生的事情,首先可能发生的事件是在Session Timeout时间段内重连成功得到SyncConnected事件,这时A可以重新升级为主,对外提供服务。如果这段时间内没有重连成功,ZK Server在Session Timeout时会将A注册的临时节点移除,并通知B和C A已经停止对外服务了,需要选出新的leader。因为A自己已经降主了,所以在选出新leader后也不会出现多主现象。如果A在Session Timeout时间段外重连又成功了,那此时肯定新的leader已经选出来了,A需要重新注册作为新的备机候选。

可以使用如下的流程图解释这个过程:

这种应用层面的方案在一定程度上解决了脑裂问题,但是会出现一段时间系统无Leader的情况,持续时间最长为Session超时时间。

总结:

结合上述分析,可以针对Session Timeout的问题得出一个应用层面的解决方案,即Client分阶段转变角色方案。如下图所示,箭头上方红色标示表示Client所处不同阶段,箭头下方蓝色标示表示Client在不同阶段的角色转变。

本文章为作者原创

Zookeeper中Session Timeout的那些事的更多相关文章

  1. 关于zookeeper中session timeout

    转自https://yq.aliyun.com/articles/117825?t=t1,主要结论如下: 经过源码分析,得出SessionTimeOut的协商如下: 情况1: 配置文件配置了maxSe ...

  2. 在Django中Session的那点事!

    1.session是什么 首先引入度娘的解释:Session:在计算机中,尤其是在网络应用中,称为“会话控制”.Session 对象存储特定用户会话所需的属性及配置信息.这样,当用户在应用程序的 We ...

  3. 项目server中设置session timeout遇到的问题

    RT:在项目server中的web.xml设置session timeout=10,当10分钟后,继续右键执行jsp文件,运行失败,如下图所示: 但是单独启动tomcat server后,在浏览器中输 ...

  4. ASP.NET中Session的sessionState 4种mode模式

    1. sessionState的4种mode模式 在ASP.NET中Session的sessionState的4中mode模式:Off.InProc.StateServer及SqlServer. 2. ...

  5. java 中Session 持久化问题

    首先: 今天发现了个session 持久化的问题 在Tomcat 停止运行后再启动  session  中保存的东西还会存在 ,百度了一下 原理 1.Session Create 时 2.Sessio ...

  6. zookeeper中Watcher和Notifications

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

  7. zookeeper中client命令实践

    Welcome to ZooKeeper! 2016-09-14 16:06:04,528 [myid:] - INFO [main-SendThread(master:2181):ClientCnx ...

  8. asp.net中Session过期设置方法

    在Asp.net应用中,很多人会遇到Session过期设置有冲突.其中,可以有四处设置Session的过期时间: 一.全局网站(即服务器)级 IIS-网站-属性-Asp.net-编辑配置-状态管理-会 ...

  9. 【Apache ZooKeeper】理解ZooKeeper中的ZNodes

    理解ZooKeeper中的ZNodes 翻译自:http://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html ZooKeeper中的 ...

随机推荐

  1. 《es6标准入门》chapter11中关于Proxy的一个错误例子的纠正

    在原书第二版的p120,这里有一个使用Proxy实现管道化调用的例子,想法很好,但是代码有问题,下面是更正之后的代码. 由于我是在node环境下运行,所以我把几个全局函数定义到global内了,如果是 ...

  2. ui-router 1.0 003 lazyloading

    ui-router lazyloading 支持懒加载, 真正需要的时候再去加载模块

  3. 使用zlib库进行目录打包

    代码很简单,具体过程就不写了. 关于加密压缩,可以看http://www.zlib.net/zlib_faq.html#faq38 中的描述,说是不支持的,但是创建的时候可以传入密码进去,不过我还没有 ...

  4. Ubuntu11.04安装引导BURG

    时间:11-05-10    BURG是一个漂亮的引导程序,可以代替ubuntu默认的引导. ubuntu11.04安装方法如下: sudo add-apt-repository ppa:n-muen ...

  5. CentOS---网络配置详解 (转)

    一.配置文件详解在RHEL或者CentOS等Redhat系的Linux系统里,跟网络有关的主要设置文件如下: /etc/host.conf         配置域名服务客户端的控制文件/etc/hos ...

  6. MySQL -- 异步I/O

    linux上,innodb使用异步IO子系统(native AIO)来对数据文件页进行预读和写请求.行为受到参数innodb_use_native_aio控制.默认是开启的,且只是适用于linux平台 ...

  7. Cortex-A15架构解析:它为什么这么强(转)

    今年的新手机趋势无异是全面向四核靠拢,不过同样是四核,在实际的性能上其实是千差万别.例如针对入门级主流市场的四核手机普遍采用的都是Cortex-A7以及 Cortex-A9 级别的CPU内核,这类内核 ...

  8. FragmentPagerAdapter 与 FragmentStatePagerAdapter 的区别

    参考链接: http://blog.csdn.net/dreamzml/article/details/9951577 简单来说前者适合静态.少量的Fragment 后者适合动态.较多的Fragmen ...

  9. 【iCore4 双核心板_ARM】例程十一:DMA实验——存储器到存储器的传输

    实验原理: DAM(直接存储器访问)传输不需要占用CPU,可以在存储器至存储器实现高速的数据 传输.本实验采用DAM2控制器的数据流0,选用通道0进行数据传输.通过LED的颜色来 判断传输是否成功. ...

  10. 【iCore4 双核心板_FPGA】例程十:FSMC总线通信实验——复用地址模式

    实验原理: STM32F767上自带FMC控制器,本实验将通过FMC总线的地址复用模式实现STM32与FPGA 之间通信,FPGA内部建立RAM块,FPGA桥接STM32和RAM块,本实验通过FSMC ...