摘要
我们了解了zk原理后,接下来就是部署zk、进行zk的运维。在部署zk的时候:zk一般作为基础架构类别的系统,也可以作为数据中间件系统,假如在公司的部署机器比较少,虽然部署的机器少,但是你别用太普通的配置。
思维导图
内容
1、单机模式如何启动zk?
一般比如zk,kafka,hbase,hdfs这种系统一般要求机器性能是比较高的。使用虚拟机的话,比如zk部署3台机器,最好用8核16g,16核32g,最好用ssd固态硬盘。
zk按照集群化3,5单节点部署,部署完毕之后,会进行恢复模式进行过半算法选举一个leader出来,只有leader可以读写,follower只能读,客户端跟leader/follower通过tcp长连接进行连接,中间靠心跳会维护一个session。往follower去写的话,其实会转发给leader,往集群里面写数据的时候,会采取一个2pc+过半写机制 数据写采用:日志文件写磁盘+znode内存数据结构 保证的是顺序一致性(不能说是强一致性或者最终一致性)。如果一定需要增加集群的QPS,我们可以往集群里面添加observer类型的节点进去就可以了,不采取过半写跟leader选举,只是同步数据,客户端查询。Mode:standalone
三台机器的小集群抗每秒十几万的并发是没有问题的,zk集群,基本上公司都够用了。
参考:https://segmentfault.com/a/11...
2、zk集群部署
zk集群部署操作参考:https://segmentfault.com/a/11...
2.1 集群部署需要多少台机器?为什么?
zk如果你用4核8G的虚拟机其实是不太靠谱的。针对于zk的话:最起码也得是:8核16G,如果有16核32G这种高配置虚拟机最好了,而且最好是SSD固态硬盘。因为3种不同配置机器由于zk的并发限制了。
`4核8G的机器:一般来说,每秒并发搞到1000是可以的。
8核16G的机器:每秒并发搞到几千是可以的。
16核32G的机器:每秒并发搞到上万或者是几万都是有可能的。`
如果你用高配置的机器(16核32G内存的机器),比如搞了3台机器,1个leader,2个follower,leader主要是写,每秒抗几万并发写入是可以的;leader+follower,读,每秒抗个5万~10万的读是没有问题的,综合可以每秒十多万的QPS都可以抗住了。
2.2 zk的读能力如何扩展;zk的写能力如何扩展?
如果用高配置的机器,zk的读并发是比较高的,只不过写QPS无法线性的扩展。增加读QPS还可以,我们只需要强制添加Observer角色节点,不能是leader或者follower(由于Observer不参与过半写机制跟过半选举leader)
由于zk在启动进入恢复模式或者宕机重新进入恢复模式的时候,zk是采用过半选举机制;假如有过半的机器同意某一个节点为leader节点,那么此节点就是leader节点。比如6台机器,过半就是3台,只要宕机不超过(6-3)台机器,就可以再次选举出leader,提供服务;假如是5台机器,过半是3台,只要宕机机器不超过2台,也可以选举提供服务,过半3跟过半大于2.5的时候,都是3台。
3、合理设置ZooKeeper的JVM参数?
1、zk能直接启动吗?
比如你现在手头搞好了几台机器,并且是那种大内存的机器,并且zk的配置都配置好了,现在准备启动了,那么zk能直接启动吗?
不能,生产环境下,是有一些特殊的东西要改一改的。
比如最最起码的一点:zk本身是用java写的,是基于JVM虚拟机来运行的,启动的是一个JVM进程,JVM进程里面会执行zk的全部代码。
2、设置JVM参数:
必须得合理的设置一些JVM的参数。主要有三大块东西,必须要合理的调优和设置的。
1、内存设置
:你首先,设置分配你的各块内存区域的大小:堆内存,栈内存,Metaspace区域的内存;根据你机器上内存的情况去设置。
举例:比如你的机器如果有16G的内存,堆内存可以分配个10G,栈内存可以分配每个线程的栈是1MB,Metaspace区域可以分配个512MB都可以。
2、垃圾回收器设置
:
小内存(32G以下):我们设置垃圾回收器,回收新生代+老年代,我们可以使用ParNew+CMS垃圾回收器进行垃圾回收。
如果是大内存机器,不建议这个组合了,可以考虑使用G1回收所有的垃圾对象,还得设置一些G1的参数,比如:region的大小,最关键的是预期的每次GC的停顿时间是多少毫秒,比如设置为100ms;然后决定G1每隔多长时间进行垃圾回收。
3、gc日志记录设置
:
线上JVM运行的时候,频繁gc问题,oom问题,加入一些参数,gc日志要写入哪个目录中,如果发生oom的话,此时要自动dump内存快照出来放哪个目录去。
3、怎样简单监控?
当你的zk启动之后,在你的公司开始使用他了,在各种情况下,比如一些运行高峰期,你应该使用jstat观察一下他的情况
,去整个观察下jvm运行的情况,包括他的新生代的对象增长速率,young gc的频率,老年代增长速率,full gc的频率。如果gc有问题,需要得进行gc调优,合理优化jvm参数。另外,如果有监控系统
,需要对zk运行时的jvm的情况进行监控,比如说gc频繁,内存使用率。
4、zk的JVM参数设置在哪里设置?
zk的启动参数设置是在:zkServer.sh 的start模块去设置。
4、zk核心参数说明
前面已经做了zk机器的配置,以及zk在机器上如何部署和配置,还有zk的jvm参数如何配置,如何给zk分配他需要的内存资源、垃圾回收器、gc日志参数。然后讲解完了上面的其实还不够,还需要在正式的启动zk之前,还需要了解下其他的一些东西;就是对zk的一些参数进行配置。zk有很多参数,所以我们需要考虑下zk的一般参数如何配置。
tickTime
:zk里的最小时间单位,是zk的基本时间单元。默认是2000毫秒,也就是2s,zk其他的一些参数就会以这个tickTime为基准来进行设置,比如有的参数就是tickTime * 2。dataDir
:主要是放zk里的内存数据快照
,因为zk里会存储很多的数据,但是这些数据在内存里有一份快照,然后在磁盘里其实也会有一份数据的快照,这样的话,比如:zk停机了,然后zk重启才能恢复之前的数据。所以dataDir主要是存放zk里面的数据快照的。dataLogDir
: 在zk原理时候,我们讲解了zk的写数据操作,它是基于2PC机制,
第一个阶段:将请求包装成写proposal,这个时候每台机器都会写入一个本地磁盘的事务日志
,主要是放一些日志数据。
一般来说建议dataDir跟dataLogDir挂载到不同的磁盘,并且最好挂载SSD固态硬盘;因为这样的话,可以保证读写速度非常快,因为dataLogDir这种事务日志磁盘写,是对zk的写性能和写并发的影响是很大的。
5、影响Leader与Follower组成集群运行的两个核心参数
这里面给大家讲解下两个比较核心的参数:initLimit跟syncLimit。
initLimit(初始化同步允许超时时间)
:zk集群启动的时候,默认值10就是:10 * tickTime=20s,leader在启动之后会等待follower跟自己建立连接以及同步数据,最长等待时间是20s,在20s内,follower一般必须要跟leader建立连接。过了这个时间之后,leader就不等follower,直接进入消息广播模式,对外提供服务了。
一般上面默认的参数是不用动的,但是假如:你的zk里存储的数据量比较大了,导致follower同步数据需要的时间比较长,此时可以调大这个参数。
syncLimit(心跳超时间隔)
:默认值5,也就是5 * tickTime,10s,这个就是指代:leader跟follower之间会进行心跳,如果超过10s没有心跳,leader就把这个follower给踢出去了,认为他已经死掉了。
6、ZK数据快照
zk里的数据分成两份:一份是在磁盘上的事务日志,一份是在内存里的数据结构,理论上两份数据是一致的,即使是有follower宕机,也是内存里的数据丢失了,但是磁盘上的事务日志都是存在的。即使有的follower没收到事务日志就宕机了,也可以在启动之后找leader去同步数据
1、什么是数据快照
数据快照是某一时刻全量内存数据的镜像,存储在磁盘文件。
2、为什么引入数据快照?
zk宕机时候,重建内存数据:比如zk宕机了,此时zk比如说在磁盘里有一份事务日志了,此时他启动之后要重建内存里的数据,如何重建呢?难道说把事务日志进行回放?一条一条重新执行每条事务日志到内存里去吗?这样肯定是不靠谱的,而是会导致zk启动很慢的。所以zk是有一个数据快照的机制。
3、zk是什么时候进行数据快照的?
事务日志的次数超过设定值后,会触发ZK dump全量内存数据到磁盘文件,生成数据快照,如下图所示.
4、数据快照创建流程以及相关的参数是什么?
数据快照创建流程流程:
1. 首先,查看事务日志数量是否达到设定次数;
2. 其次,如果超过指定次数,则切换事务日志文件(为了和数据快照保持同步);
3. 其次创建异步线程,专门用于dump内存数据到磁盘文件;
4. 用ZXID作为文件名,然后将会话信息和DatatTree分贝序列化写入文件;
快照创建参数:
每次执行一定的事务之后,就会把内存里的数据快照存储到dataDir这个目录中去,作为zk当前的一个数据快照。现在在磁盘事务日志里有1000个事务,然后把1000个事务对应的内存数据写入到dataDir里作为一个数据快照,接下来继续写事务日志,比如此时事务日志里有1032个事务,此时zk重启,他可以直接把包含1000个事务的快照直接加载到内存里来。然后1000之后的32个事务,1001~1032的事务,在内存里回放一遍,就可以在内存里恢复出来重启之前的数据了。
究竟是写多少个事务日志存储一个快照呢?实际上它有一个参数叫做snapCount;snapCount:100000,默认是10万个事务存储一次快照。
即使没到10万事务,就重启了,此时是没有快照文件的,但是此时是没有关系的,他认为10万个事务以内,不需要快照,因为10万个事务日志以内,可以直接读取事务日志,回放到内存就重建内存数据了。
7、一台机器上最多能启动多少个ZooKeeper客户端?
连接数:
在zk客户端上可能会运行一个Java开发的系统去使用zk,比如说Kafka(虽然是Scala写的,也是JVM类的语言),HBase,Canal,HDFS,比如说Canal比如部署在一台机器上,此时他会去使用zk,他就是一个zk的客户端。当他们使用zk的Java API,去建立一个zk客户端,zk客户端负责跟zk servers进行连接和通信。
但是一台机器上,我们可以创建多少个zk客户端?也就是说可以跟zk servers建立多少个连接呢?
这个是有限制的,默认来说60;
3.4.0以前是10个
1、参数:maxClientCnxns
我们通过参数:maxClientCnxns可以设置某一个客户端机器最大连接zk server的连接个数。 所以如果我们自己开发一个系统去使用zk的话,一台机器上,你一般是就用一个zk客户端去跟zk servers进行交互就可以了,不要无限制的搞很多的zk客户端,会连接不上去的,他zk servers最多只能允许你的一台机器跟他建立60个连接。
8、一个znode最大存储数据量大小
一个znode中最多可以存储多大数据量,这个其实也是一个关键点。你肯定会不停地往zk里面写数据;往zk里面写数据其实就是一个一个的znode,一个znode最多可以存储多少数据呢?
默认是:1mb,1048575bytes(字节)。
一般来说建议,不要在znode中存储的数据量过大,一般来说几百个字节,几百kb,就可以了。
9、Leader与Follower是通过哪两个端口进行通信?
之前我们配置zk集群时候,每台机器上都需要配置如下:
server.1=zk01:2888:3888
第二个端口
:3888,一般来说每台机器的3888端口,是用来在集群恢复模式的时候进行leader选举投票的,也就是说所有的机器之间进行选举投票的时候就是基于3888端口来的。
第一个端口
:2888,2888的端口,是用来进行leader和follower之间进行数据同步和运行时通信的。
10、事务日志和数据快照是如何进行定时清理?
你不停的让zk运行,那么事务日志会越来越多,但是不可能是无限多的,所以他会切割出来多个事务日志文件,也就是事务日志文件它是有多个的。另外的话每次你执行一次数据快照,每次都有一个独立的数据快照文件,最后的话你zk磁盘文件上会有多个事务日志文件,多个数据快照文件。
默认来说没有开启定时清理数据文件的功能
。
11、2PC阶段中写入磁盘的事务日志有没有丢失的风险?
1、为什么有风险?(写日志原理)
是这样的?假如你的写请求proposal过去到follower了,leader会通知过半的follower去写事务日志。然后返回ack之后,才会让leader去发送commit的请求,那么实际上来说的话,在 事务进行commit提交的时候,有没有日志丢失的风险?
其实是有的,默认情况下,在2PC阶段的第一个阶段里,各个机器把事务日志写入磁盘,此时一般是只能进入os cache的,没有直接进入物理磁盘上去。
所以的话在commit提交的时候一般默认会强制把写的事务从os cache通过fsync到磁盘上去。
它有一个参数叫做:forceSync:yes //默认值是yes,也就是说他默认情况下就会强制把事务同步到磁盘上去。你也可以将其改为no,这样可以提高机器的性能。建议设置为yes,降低事务日志丢失风险。
2、写事务日志到磁盘的效率如何?
1、写日志是顺序写磁盘,顺序写磁盘跟随机写内存的性能是差不多的,性能是很高的。之前给大家讲解Kafka的时候就也是说过,顺序写磁盘性能很高,
2、而且,刚开始的话,它是写到操作系统的缓存里面去的:os cache,所以也保证了他的性能就更高了,只是在commit的时候,需要fsync到磁盘上去,但是fsync之前机器坏了,有可能会丢失部分os cache里没刷入磁盘的数据,如果是follower宕机还好,因为follower会从leader同步数据,但是如果是leader宕机的话,这个就有可能导致数据丢失。
总结:
大家要清楚一点,就是默认会将数据通过参数forceSync:yes设置将数据刷到磁盘里面去的
12、跟leader自己相关的两个参数的说明
leaderServers
:默认值是yes,就是说leader是否接受客户端的连接,默认是可以的,默认客户端是可以跟leader建立连接的。但是你也可以设置成no,但是此时客户端只能跟follower进行连接,因此客户端跟follower进行了连接,所有写请求由follower转发给leader,然后leader主要接受follower的转发写请求进行处理。其实也可以,一般来说不这么设置。
cnxTimeout
:默认5000,在进行leader选举的时候,各个follower机器会基于3888那个端口建立TCP连接,在这个过程中建立TCP连接的超时时间。
在启动zk集群之前,有哪些参数是必须要设置的,必须要设置的参数,即使有,也全都在zoo_sample.cfg,主要是以下3个参数需要设置
:
1、主要是把zk集群的信息配置进去:server.1,server.2。
2、每台机器配置dataDir,dataLogDir。
3、开启自动清理数据文件的参数。
配置完成之后,就可以写数据了。 然后就可以基于zkServer.sh命令,
分别启动leader和follower等多个节点。
13、zookeeper提供给运维人员命令说明
假设你硬件配置、JVM配置(zkServer.sh)、日志参数配置(zoo.cfg)都弄好了之后,整个zk集群启动,你作为zk运维;你需要去关注zk集群的运行状态。这个时候zk提供了一些命令供我们使用。其实怎么用了?如下:
1、命令模版
conf(查看配置)、cons(查看连接)、crst(重置客户端统计)、dump(输出会话)、envi(查看环境)、ruok(检查是否在运行)、stat(查看运行时状态)、srst(重置服务器统计)、wchs(查看watcher信息)、wchc(输出watche详细信息)、wchp(输出watcher,以znode为单位分组)、mntr(输出比stat更详细的)
echo xxx | nc ip 客户端连接端口
2、xxx详细说明
查看zk配置
:conf查看环境:
envi查看连接数量
:cons查看详细信息
:mntr
14、zk监控
1、jstat监控
你手上有一个zk集群的话,你得经常去看看他的JVM运行情况。他的内存使用情况,以及gc情况;
Jstat -gc pid 最多显示多好行 每多少毫秒显示一次
jstat -gc 82826 1000 1000
2、jconsole监控
JDK自带了一个可视化的JVM进程内存分析的工具,JConsole
一般在你自己的笔记本电脑上就可以打开使用,百度一下,看看就知道了
此时需要设置ZOOMAIN参数:对于zk而言,我们在他的启动脚本下,可以修改其脚本参数。我们查找ZOOMAIN参数:
参数如下:
-Dcom.sun.management.jmxremote.port=21811
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
15、加入Observer节点提升读QPS
之前给大家讲过,如果你现在有一个zk集群,想要线性增加其读的QPS;你该如何做呢?
1、你可以配置一台机器上的zk,你讲下面参数设置如下:peerType=observer
2、另外所有机器的配置文件,都要加入一个server.4=zk04:2888:3888:observer;//除了自身知道自己是一个observer,还得让所有机器知道observer.
这样的话leader仅仅会同步数据给他,但是他不参与leader选举,也不参与过半写机制。只是慢慢去同步数据。
其他就没什么了?其他zk的运维就是:看看磁盘空间是否足够,zk集群建立的连接是否过多,或者就是最多升级一下版本,3.4.5够用了。
总结:
到此,zk集群的部署、参数的设置、监控运维管理基本就这样了。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。