一、zookeeper集群简介
Zookeeper集群的特点:可复制性
强烈建立使用奇数个服务器,每个服务运行在单独的机器上.容错激设置至少需要3台服务器.
记录:
1.设置zookeeper集群是一定要部署为2xF+1(即奇数)个server,这样可以允许F个Server出错(宕机或其他)。即:假设有三台server,则最多可以允许一台服务器宕机。集群继续正常工作。
2. 设计zookeeper集群时,为了尽量抬高可靠性、容错性。部署服务器的时候,尽量让服务器位于不同的机房、或者在同一个机房中连接不同的交换机。防止一台交换机出错时,导致整体不可用。
二、集群中的配置介绍
需要注意的配置
1.initLimit:
集群中的小弟follower服务器,和领导leader服务器之间完成初始化同步连接时的能接受的最大心跳数,
此时如果集群环境非常大,同步数据的时间较长,这个参数我们需要进行适当调整.
注意,在zookeeper中,任何时间的设置都是以ticktime的倍数来进行定义,如果我们设置initLimit=2.那我们能接受的最大时间就是ticktime*2
2.syncLimit:
follower和leader之间请求和应答能接受的最大心跳数
集群节点的配置
server.id = host:port:port
id:通过在各自的dataDir目录下创建一个myId的文件来为每台机器赋予一个服务器id,这个id我们一般用基数数字表示
两个port:第一个follower用来连接到leader,第二个用来选举leader
记录:了解Leader选举
Zookeeper的启动过程中leader选举是非常重要而且最复杂的一个环节。那么什么是leader选举呢?zookeeper为什么需要leader选举呢?zookeeper的leader选举的过程又是什么样子的?
首先我们来看看什么是leader选举。其实这个很好理解,leader选举就像总统选举一样,每人一票,获得多数票的人就当选为总统了。在zookeeper集群中也是一样,每个节点都会投票,如果某个节点获得超过半数以上的节点的投票,则该节点就是leader节点了。
以一个简单的例子来说明整个选举的过程.
假设有五台服务器组成的zookeeper集群,它们的id从1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的.假设这些服务器依序启动,来看看会发生什么 。
1) 服务器1启动,此时只有它一台服务器启动了,它发出去的报没有任何响应,所以它的选举状态一直是LOOKING状态
2) 服务器2启动,它与最开始启动的服务器1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是3),所以服务器1,2还是继续保持LOOKING状态.
3) 服务器3启动,根据前面的理论分析,服务器3成为服务器1,2,3中的老大,而与上面不同的是,此时有三台服务器选举了它,所以它成为了这次选举的leader.
4) 服务器4启动,根据前面的分析,理论上服务器4应该是服务器1,2,3,4中最大的,但是由于前面已经有半数以上的服务器选举了服务器3,所以它只能接收当小弟的命了.
5) 服务器5启动,同4一样,当小弟
三、zookeeper集群搭建
1>机器及端口准备
注意:防火墙问题,关闭防火墙或是防火墙过滤端口优先选择过滤端口
需要在防火墙配置中(/etc/sysconfig/iptables)过滤以上使用到的端口号(Centos7默认防火墙firewall)
2>安装JDK 【此步骤省略】。
3>Zookeeper压缩包上传到服务器(这儿使用的是zookeeper-3.4.10.tar.gz);
压缩包下载地址:
https://archive.apache.org/dist/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz
4>将zookeeper压缩包解压到/opt/zookeeper/目录下(这儿看个人公司要求,我们的组件默认都在此目录下)
tar -zxvf zookeeper-3.4.10.tar.gz -C /opt/zookeeper/
5>将 zookeeper-3.4.10/conf下zoo_sample.cfg 文件改名为 zoo.cfg
mv zoo_sample.cfg zoo.cfg
6>修改/opt/zookeeper/zookeeper-3.4.10/conf/zoo.cfg
vim /opt/zookeeper/zookeeper-3.4.10/conf/zoo.cfg
zoo.cfg文件配置如下:(当前为我们的外网环境配置示范)
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.(保存数据的路径,需要绝对路径)
dataDir=/data02/zookeeper/data //数据存储路径
dataLogDir=/data01/zookeeper/log //日志存储路径
# the port at which the clients will connect
clientPort=9611 //当前实例端口号
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.1= 10.123.14.32:9612:9613
server.2= 10.123.14.33:9612:9613
server.3= 10.123.14.34:9612:9613
参数说明 :
注意:data01下的zookeeper需手动创建(mkdir zookeeper)
data02下的zookeeper/data需手动创建
7>同步/opt/zookeeper/zookeeper-3.4.10目录内容到另外两台机器(可在另外两台机器重复以上操作也可用命令)
scp /opt/zookeeper/zookeeper-3.4.10 [email protected]:/opt/zookeeper/
scp /opt/zookeeper/zookeeper-3.4.10 [email protected]:/opt/zookeeper/
注意:zookeeper目录需要手动创建(在opt/下执行 mkdir zookeeper) 否则会找不到路径
8>在每个实例配置文件zoo.cfg中dataDir指定的路径下(即/data02/zookeeper/data)创建一个myid文件,myid文件内容即为zookeeper实例的序列号,第一个实例即1,第二个即2,以此类推(即server.X= 10.123.14.32:9612:9613中的X)
记录:dataDir和dataLogDir
zookeeper官方建议我们添加上dataLogDir来存放事务日志。如果只有dataDir目录而没有dataLogDir目录的话,它会把运行日志和事务日志都放在dataDir的那个目录上面去,事务日志和运行日志有什么区别?这个事务日志就相当于我们zookeeper的数据库,需要使用到读取和恢复等功能的时候,它就需要这么一个数据库来恢复。
9>修改环境变量 vim /etc/profile(已做jdk环境变量可忽略)
export ZOOKEEPER_HOME=/usr/local/zookeeper-3.4.10
export PATH=$ZOOKEEPER_HOME/bin:$PATH
配置生效:
source /etc/profile
10>添加zookeeper用户并设置密码(看个人公司要求,为规避风险尽量避免使用root用户)
useradd zookeeper
passwd zookeeper
删除用户:userdel 用户名
11>将opt下的zookeeper所属切换到zookeeper用户下,文件赋予zookeeper用户权限
在opt路径下执行(数据日志和事务日志文件夹需同样的操作)
chown -R zookeeper:zookeeper zookeeper/
12>将当前的root用户切换到zookeeper用户
su zookeeper
13>集群启动-在zookeeper用户下分别启动集群下各个zookeeper实例(规避风险-非root用户启动)
bin/zkServer.sh start
14>查看zk启动状态
bin/zkServer.sh status
至此,搭建完成
三、zookeeper集群测试
客户端连接:
./bin/zkCli.sh -server 10.123.14.33:9611
一些操作命令
[zk: 10.123.14.33:9611(CONNECTED) 2] create /zk_test hello
Created /zk_test
[zk: 10.123.14.33:9611(CONNECTED) 3] get /zk_test
hello
cZxid = 0x100000003
ctime = Wed Sep 19 18:04:00 CST 2018
mZxid = 0x100000003
mtime = Wed Sep 19 18:04:00 CST 2018
pZxid = 0x100000003
cversion = 0
dataVersion = 0
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 5
numChildren = 0
[zk: 10.123.14.33:9611(CONNECTED) 4] set /zk_test fuck
cZxid = 0x100000007
ctime = Wed Sep 19 18:09:32 CST 2018
mZxid = 0x100000008
mtime = Wed Sep 19 18:09:40 CST 2018
pZxid = 0x100000007
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
[zk: 10.123.14.33:9611(CONNECTED) 5] get /zk_test
fuck
cZxid = 0x100000007
ctime = Wed Sep 19 18:09:32 CST 2018
mZxid = 0x100000008
mtime = Wed Sep 19 18:09:40 CST 2018
pZxid = 0x100000007
cversion = 0
dataVersion = 1
aclVersion = 0
ephemeralOwner = 0x0
dataLength = 4
numChildren = 0
[zk: 10.123.14.33:9611(CONNECTED) 6] delete /zk_test
[zk: 10.123.14.33:9611(CONNECTED) 7] ls /
[zookeeper]
[zk: 10.123.14.33:9611(CONNECTED) 8]
四、zookeeper高可用测试
2. 运行kill -9 命令杀死三个zookeeper中的两个。集群全部失效。
总结:也就是说三台服务器中,如果一台宕机,集群是可以继续正常运行的,但是两台宕机就不可以了。
查阅官网文档之后,发现如下的doc:
Cross Machine Requirements
For the ZooKeeper service to be active, there must be a majority of non-failing machines that can communicate with each other. To create a deployment that can tolerate the failure of F machines, you should count on deploying 2xF+1 machines. Thus, a deployment that consists of three machines can handle one failure, and a deployment of five machines can handle two failures. Note that a deployment of six machines can only handle two failures since three machines is not a majority. For this reason, ZooKeeper deployments are usually made up of an odd number of machines.
To achieve the highest probability of tolerating a failure you should try to make machine failures independent. For example, if most of the machines share the same switch, failure of that switch could cause a correlated failure and bring down the service. The same holds true of shared power circuits, cooling systems, etc.
总结起来,就是如下几点:
1.设置zookeeper集群是一定要部署为2xF+1(即奇数)个server,这样可以允许F个Server出错(宕机或其他)。即:假设有三台server,则最多可以允许一台服务器宕机。集群继续正常工作。
2. 设计zookeeper集群时,为了尽量抬高可靠性、容错性。部署服务器的时候,尽量让服务器位于不同的机房、或者在同一个机房中连接不同的交换机。防止一台交换机出错时,导致整体不可用。
五、异常情况----安装或启动异常
1>连接异常:(服务是否正常启动,端口号是否已过滤开放)
端口号开放:
查看防火墙状态
systemctl status firewalld.service
启动|关闭|重新启动 防火墙
systemctl [start|stop|restart] firewalld.service
2>Error contacting service. It is probably not running.
网上问题答案有许多种,一一归纳:
1. zoo.cfg配置文件中指定目录却没有创建! 创建相应目录即可。
2. zoo.cfg中dataDir指定路径为Myid文件的路径。
Myid内容与:server.?=localhost:2888:3888 中你所设置?一致!
3.使用service iptables stop 关闭防火墙
使用service iptables status确认
4. 1,打开zkServer.sh 找到
status)
STAT=`echo stat | nc localhost $(grep clientPort "$ZOOCFG" | sed -e 's/.*=//') 2> /dev/null| grep Mode`
在nc与localhost之间加上 -q 1 (是数字1而不是字母l)
如果已存在则去掉
5.2181端口被占用! #我就是死在这的,死了很久很久。。
zkServer.sh stop #先停止zookeep
netstat -an | grep 9611 #查看端口是否占用,如果占用
clientPort = 9611 #随便找个没占用的端口号!