工作当中我所解决的一个线上问题

工作当中很多场景用到了zookeeper集群,比如利用他的一致性能力、节点监听能力等实现业务上的多种功能。
这次遇到的问题是zookeeper磁盘util过高。

先通过iostat查看磁盘的await指标和util指标,如下图所示:
工作当中我所解决的一个线上问题

工作当中我所解决的一个线上问题

await:每一个IO请求的处理的平均时间(单位是微秒毫秒)。这里可以理解为IO的响应时间,一般地系统IO响应时间应该低于5ms,如果大于10ms就比较大了。

%util:在统计时间内所有处理IO时间,除以总共统计时间。例如,如果统计间隔1秒,该设备有0.8秒在处理IO,而0.2秒闲置,那么该设备的%util = 0.8/1 = 80%,所以该参数暗示了设备的繁忙程度。一般地,如果该参数是100%表示设备已经接近满负荷运行了(当然如果是多磁盘,即使%util是100%,因为磁盘的并发能力,所以磁盘使用未必就到了瓶颈)。

查看线上的机器配置:

~$ echo conf | nc xxx 2181 
clientPort=2181
dataDir=/data0/zookeeper/version-2
dataLogDir=/data0/zookeeper/version-2
tickTime=2000
maxClientCnxns=60
minSessionTimeout=4000
maxSessionTimeout=40000
serverId=22
initLimit=10
syncLimit=5
electionAlg=3
electionPort=3888
quorumPort=2888
peerType=0

工作当中我所解决的一个线上问题

解决思路

dataDir=/data
dataLogDir=/datalog

dataLogDir如果没提供的话使用的则是dataDir。zookeeper的持久化都存储在这两个目录里。dataLogDir里是放到的顺序日志(WAL)。而dataDir里放的是内存数据结构的snapshot,便于快速恢复。为了达到性能最大化,一般建议把dataDir和dataLogDir分到不同的磁盘上,这样就可以充分利用磁盘顺序写的特性。

多挂一个盘,将snapshot和log分开,17:36分做了变更,util下降了3个百分点,效果不够理想,如下图

工作当中我所解决的一个线上问题

主要的压力在事务日志dataLogDir上,如下图
工作当中我所解决的一个线上问题

其中,vda对应的是/data0,vdb对应/data1
其实通过测试环境中zk data路径下的日志文件列表是可以预见到的

total 219M
-rw-r--r-- 1 root root  65M May 15 18:39 log.18ddb6a1
-rw-r--r-- 1 root root  65M May 15 18:45 log.18deff56
-rw-r--r-- 1 root root  65M May 15 18:47 log.18e073c0
-rw-r--r-- 1 root root  65M May 15 18:49 log.18e18db7
-rw-r--r-- 1 root root  65M May 15 18:53 log.18e28415
-rw-r--r-- 1 root root  65M May 15 18:55 log.18e401c6
-rw-r--r-- 1 root root  65M May 15 18:58 log.18e520c8
-rw-r--r-- 1 root root  65M May 15 19:00 log.18e62b32
-rw-r--r-- 1 root root  65M May 15 19:05 log.18e71067
-rw-r--r-- 1 root root  65M May 15 19:09 log.18e870b7
-rw-r--r-- 1 root root  65M May 15 19:15 log.18e9d86a
-rw-r--r-- 1 root root  65M May 15 19:18 log.18eb58bb
-rw-r--r-- 1 root root  65M May 15 19:20 log.18ec98ef
-rw-r--r-- 1 root root  65M May 15 19:23 log.18ed7fe9
-rw-r--r-- 1 root root  65M May 15 19:25 log.18ee9709
-rw-r--r-- 1 root root  65M May 15 19:28 log.18ef6b2a
-rw-r--r-- 1 root root 164K May 15 18:39 snapshot.18deff54
-rw-r--r-- 1 root root 164K May 15 18:45 snapshot.18e073bd
-rw-r--r-- 1 root root 164K May 15 18:47 snapshot.18e18db5
-rw-r--r-- 1 root root 165K May 15 18:49 snapshot.18e28411
-rw-r--r-- 1 root root 165K May 15 18:53 snapshot.18e401c4
-rw-r--r-- 1 root root 165K May 15 18:55 snapshot.18e520c3
-rw-r--r-- 1 root root 164K May 15 18:58 snapshot.18e62b2c
-rw-r--r-- 1 root root 165K May 15 19:00 snapshot.18e71065
-rw-r--r-- 1 root root 165K May 15 19:05 snapshot.18e870b4
-rw-r--r-- 1 root root 164K May 15 19:09 snapshot.18e9d867
-rw-r--r-- 1 root root 164K May 15 19:15 snapshot.18eb58b9
-rw-r--r-- 1 root root 165K May 15 19:18 snapshot.18ec98ec
-rw-r--r-- 1 root root 164K May 15 19:20 snapshot.18ed7fe7
-rw-r--r-- 1 root root 165K May 15 19:23 snapshot.18ee9705
-rw-r--r-- 1 root root 165K May 15 19:25 snapshot.18ef6b28

可以看出,log文件大小占比在90%以上。

参数 说明
dataDir 就是把内存中的数据存储成快照文件snapshot的目录,同时myid也存储在这个目录下(myid中的内容为本机server服务的标识)。写快照不需要单独的磁盘,而且是使用后台线程进行异步写数据到磁盘,因此不会对内存数据有影响。默认情况下,事务日志也会存储在这里。建议同时配置参数dataLogDir, 事务日志的写性能直接影响zk性能。
dataLogDir 事务日志输出目录。尽量给事务日志的输出配置单独的磁盘或是挂载点,这将极大的提升ZK性能。 由于事务日志输出时是顺序且同步写到磁盘,只有从磁盘写完日志后才会触发follower和leader发回事务日志确认消息(zk事务采用两阶段提交),因此需要单独磁盘避免随机读写和磁盘缓存导致事务日志写入较慢或存储在缓存中没有写入。

此路未解决问题,不过引用文章2中提到了另一种解决思路——写内存:
Zookeeper有两种日志,一种是snapshot(快照),另一种是log(事务日志),出问题的点在于事务日志。

写内存,/dev/shm是系统内存划分出的一块区域,默认大小是系统内存的一半,可以通过df -h看到。
我们可以把事务log写到这里单独mount一块SSD,这就不说了,是钱的问题。
这里我最终选择的写内存的方式。

而由于我们的系统是基础组件,数据不容有失,没办法使用写内存的方式了。
目前,我们的机器来自腾讯云,机器磁盘挂载的云盘,我们打算额外挂载一块SSD磁盘用来存放zk的事务日志。

查看磁盘写性能

~$ time dd if=/dev/zero of=/data/test.dbf bs=1M count=10000
10000+0 records in
10000+0 records out
10485760000 bytes (10 GB) copied, 48.5508 s, 216 MB/s

real    0m48.552s
user    0m0.007s
sys     0m13.156s

查看磁盘是否为SSD盘

cat /sys/block/sda/queue/rotational 

注意:
命令中的sba是你的磁盘名称,可以通过df命令查看磁盘,然后修改成你要的。

结果:
返回0:SSD盘
返回1:SATA盘

或者,使用如下命令,看第四列,不过在腾讯云机器上无任何输出

# lsscsi
[0:0:0:0] disk SEAGATE ST3300657SS ES62 - 
[0:0:1:0] disk ATA INTEL SSDSA2CW16 0362 /dev/sda
[0:0:2:0] disk ATA INTEL SSDSA2CW16 0362 /dev/sdb
[0:0:3:0] disk ATA INTEL SSDSA2CW16 0362 /dev/sdc
[0:1:0:0] disk Dell VIRTUAL DISK 1028 /dev/sdd
[3:0:0:0] cd/dvd TEAC DVD-ROM DV-28SW R.2A /dev/sr0

更换为SSD磁盘后,zk机器的util指标如下,已经控制到合理范围:

工作当中我所解决的一个线上问题

引用文章:

Linux iostat监测IO状态 http://www.orczhou.com/index.php/2010/03/iostat-detail/
解决Zookeeper占用IO过高的问题 https://www.good21.com/2017/03/01/fix-zookeeper-io/
为什么zookeeper会导致磁盘IO高 http://woodding2008.iteye.com/blog/2327100
Zookeeper的配置 http://www.cnblogs.com/yuyijq/p/3438829.html
ZooKeeper配置详解 https://my.oschina.net/xiaotian120/blog/194820
SATA SAS SSD 硬盘介绍和评测 https://blog.csdn.net/chen_fly2011/article/details/56665537
linux查看磁盘是否SSD盘 http://www.linuxdiyf.com/linux/21437.html
Linux中查看是否是固态硬盘(SSD)https://blog.csdn.net/justlinux2010/article/details/10333921

上一篇:今年云栖大会的新亮点


下一篇:慢SQL治理分享