Zookeeper watch倾斜?

记一次Zookeeper生产问题定位

新手向,大佬莫搞

1.问题背景

了解Druid想必都知道Druid对Zookeeper是强依赖,Druid的任务调度,数据负载均衡等等都是组件服务之间通过Zookeeper通信实现的。为此,在生产环境上我们也自运维了一个Zookeeper集群,专门用来为Druid服务。相应的,我们也部署了一些监控脚本,以实时关注Zookeeper集群的健康状态。今天的这个问题也是通过这些告警信息反映出来的。
问题的主要现象是,Zookeeper集群会偶尔告警,ZNode超过阈值,ZWatch超过阈值。这个情况之前也有出现过,但是因为部门这边没有人深入的了解过Zookeeper组件,加之这个阈值不会持续,所以这个问题的研究虽然提上了日程,但是迟迟没有花时间去解决。最近这方面的告警愈发的频繁了,考虑到我们Druid集群的数据量越来越大,出于对组件服务稳定性和服务能力的保障,我们决定对这个问题进行一次“深入”地研究。

2. 动手之前的疑惑...

即使没有用过Zookeeper,相信大家也都应该了解它是干嘛的。它是一个开源的分布式协调服务,主要用于解决分布式场景下数据一致性问题。 那么对于它的客户端而言,看到的数据应该是一致的,那么既然是一致的,为什么我们的告警只有那么一两台显示ZNode和ZWatch超过阈值呢?呵!莫非我的认知是错误的?嗯,得验证!
所以我的第一个目标,确认一个问题,ZNode和ZWatch在各个服务节点上都一致?

3. 查看集群指标

目前Zookeeper集群的监控信息获取大致有是三个途径:

  • 四字命令:一些由四个字母组成的命令,可以通过socket发送给zookeeper服务器以返回需要的指标信息,例如我们关心的znode和zwatch数量,客户端连接数等等;
  • JMX: 可以通过jdk自带的jconsle查看服务进程的相关信息;
  • AdminServer: 在zookeeper 3.5.0中,Zookeeper内嵌了jetty服务,以提供http接口给管理员。遗憾的是我们的生产集群用的是zookeeper 3.4.6,所以,我全程没用这个东西。 JMX 我也没用,因为我们出现的问题跟节点压力应该无关,所以进程的一些信息只是通过简单的java自带命令行工具查看了。

3.1 部分四字命令

下面是定位过程中会用到的一些四字命令说明:

命令 作用
mntr 这个命令一般是用户集群监控用的,返回集群大部分的指标信息,感觉从每个命令中抽出一部分指标组成返回的结果
stat 返回Zookeeper服务节点的一些状态信息和客户端的连接状况
srvr 返回zookeeper服务节点的指标信息,跟stat相似,但是没它那么详细,但是看起来更加简洁
ruok 检测zookeeper指定的zookeeper服务器是否能够正常服务,如果服务正常就会返回imok。值得这个只是检测单个节点的服务,即使得到结果是imok也不能表名这个节点在集群中能够提供正常服务。imok只能表明它作为单个zookeeper服务是OK的。
wchs 查看节点watch数量

以下是每个命令返回的结果展示:

  • Mntr


    Mntr
  • Stat


    Stat
  • Srvr


    Srvr
  • Ruok


    Ruok
  • Wchs


    Wchs

3.2 Zxid和Mode

上一节的一些命令都会带有这两个属性,这里想对他们做稍微详细一点的说明。
Mode
在Zookeeper集群中,服务的角色类型一共有三种,分别是Leader,FollowerObserver。其中三个节点都可以为客户端提供读服务,但是只有Leader能够提供写服务。而Follower和Observer的区别在于Observer参与Zookeeper集群的Leader选举和"过半写成功"机制。所以Observer能够在影响集群的其他性能的情况下,提升集群的读性能。

Zxid
作为分布式协调服务,Zookeeper实现了顺序一致性。顺序一致性要求Zookeeper对于客户端请求的事务操作要严格按照先后顺序执行,而且不同的事务之间本就可能有先后顺序的依赖关系。例如C事务的执行和提交需要A,B事务的完成。
ZAB(Zookeeper原子广播协议)的事务提交过程类似于二阶段提交,其消息广播协议具有FIFO特性,这样可以确保事务消息在网络广播的发送和接受过程中具有顺序性。在广播的过程中,Zookeeper的leader会根据客户端的事务请求生成一个Proposal,同时为这个Proposal生成一个全局单调递增的Zxid(事务ID)。Zxid是一个64位数,其中低32位表示的是事务操作顺序。高32位可以的集群Leader的"朝代",即epoch,也是递增的,每次有新的leader产生,它就会从本地的事务日志中取出最大的Zxid,解析出到高32位,并进行加1操作,之后再将低32位置为0。它表示了leader的更迭,当然还有其他的用处,这里与我们需要定位的问题没有太大联系,不做赘述。
ZAB通过Zxid对Proposal进行排序与处理,以确保顺序一致性。Leader会为每个Follower维护一个FIFO的事务队列,确保每个事务都是按照该Zxid递增处理的。
所以我们可以通过Zxid判断集群之前的数据同步等相关的操作是否有异常。

四. 问题分析定位流程

  1. 查看每个节点的Znode和Zwatch
    通过命令echo mntr | nc <host> <port>查看了每个Zookeeper节点的状态,发现不同的节点之间Znode的数量基本一致,5台节点中有3台的ZWatch在75W左右。但是,其中有2台节点的ZWatch数量比其他的节点多了10W,在85W左右。
    至此,我们大概可以可以得出结论,ZNode在不同的节点之间都是一样的,但是ZWatch不一定。

但是为什么呢?为什么ZNode在每个节点之间都是一样的,而ZWatch不是?

其实对于前者,我们很好理解。因为Zookeeper保证了单一视图,即无论client连接的是哪个节点 ,他们看到的数据都是一样的(无法确保每时每刻每个客户端看到的视图都是一样的,但是一段时间后最终是一样的)。所以每个节点的数据,这里就是ZNode都是一样的。
而ZWatch作为Zookeeper客户端对服务端添加的一个监听。并不是为了实现单一视图,实际上真正关心这个ZWatch的只有它的创建者,即创建这个Watch的客户端。客户端并不会关心别人创建的ZWatch,同时它们也没有这些ZWatch的回调函数。
查看了一下Zookeeper的客户端代码,就会发现,实际上客户端创建的ZWatch是他们自己通过WatchManager维护的。也就是说ZWatch的数量是由客户端决定的,客户端创建的ZWatch比较多,那么他连接的服务端ZWatch就会多一些。

  1. 确认客户端问题
    在第一步中我们推断出是因为客户端导致的ZWatch数量有差距,但是为什么只有两台比其他的节点多,而其他的节点又比较均衡呢?
    这里我猜测有两个原因:其一,如果每个客户端创建的ZWatch数量相差不多的情况下,客户端连接倾斜的话,则有可能导致ZWatch的倾斜;其二,如果客户端连接没有倾斜的话,那么某些客户端创建的ZWatch数量比较多的话,也会导致其连接的服务端ZWatch倾斜。

针对以上两个猜想,我开始一一验证。首先是客户端连接是否会倾斜?
我们平时编码Zookeeper客户端时都是把服务器列表作为构造参数传递进去的。所以这一块我追了一下Zookeeper客户端的源码,想看看他是怎么处理这个列表的。这一看,透透的!
在创建Zookeeper客户端的时候,ZK会把我们host列表封装到HostProvider对象中,在这个对象中他会把我们的host放到一个列表中,并对这个列表进行shuffle,如下:

^_^

之后客户端就会按照这个shuffle后的顺序连接服务端,连接断开时也会拿列表中的下一个host进行连接。即使是同一个list,shuffle后的顺序也不一定是一样的。这就确保了只要服务端地址的配置是一样的,那么每个客户端的连接都是随机的,基本上不会有连接倾斜的情况发生。

从上面的分析我们可以看到,只要配置的服务端host是一致的,客户端基本上不会出现连接倾斜的情况。那么我们就需要验证第二种猜想了,说是猜想,其实从我们上面的分析来看,如果某些客户端创建的ZWatch数量比较多的话,肯定是会导致其连接的服务端ZWatch倾斜。我要做的其实就是找出这些客户端。
我们再回头看看问题。Druid作为Zookeeper的客户端,其每个节点服务都是Zookeeper的客户端。首先是historical节点,生产上historical节点数量远大于5(Zookeeper集群节点数量),所以相对而言,这些节点的连接都会相对均衡一些,即便是有差距,也是在很小的区间内波动。同理,MiddleManger和Broker的数量也是远大于5的。
与他们不同的就是Druid的主节点了,目前生产上的主节点采用的是HA,而Druid的主节点我们可以理解有两个,一个是Coordinator服务,Overlord服务。备用节点不考虑的话,也就是说我们会有2个特殊的客户端。
哎!!!好像跟ZK集群的情况对应上了。是不是这两个服务导致的ZWatch分布不均衡。那我们就得先找到这个两个客户端连接的Zookeeper服务器。
0X01
首先查看主节点的进程,注意要是主节点。jps -ml

主节点

获得主节点进程号。
0X02
查看主节点监听的端口号(ZK客户端)netstat -anp |grep <pid>
找服务器

这就找到了主节点连接的Zookeeper服务器,另一个主节点同理。
这样就确认了2台Zookeeper服务端。通过srvr命令查看各个节点Watch数量。果然,这两个节点的ZWatch数量比其他三台要多。与预期相符!

小结:

不结了!就跟上面说的一样,Zookeeper服务在大部分场景下还是比较稳定的。在高并发场景下可能出现问题(反正目前我们是没有遇到过),这种情况下可能需要考虑扩容,或者增加Observer节点。再者,也有可能出现数据同步的问题(我们也没遇到过^ _ ^),可以试试跟官网学习,停服务,删除所有的snapshot文件和transactionLog,重启!
还有就是Zookeeper源码导入和编译测试。需要用ant转成Eclipse的项目才能导入到IDEA,我也不会用ant,网上也有一些东西,以后要是遇到这个问题,可以搜搜,谨记!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270