Zookeeper学习与实践

ZooKeeper是一个开源的分布式服务框架,它是Apache Hadoop项目的一个子项目,主要用来解决分布式应用场景中存在的一些问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置管理等,它支持Standalone模式和分布式模式(一个Leader,多个Follower),在分布式模式下,能够为分布式应用提供高性能和可靠地协调服务。

ZooKeeper集群中只有一个角色为Leader的节点,其他节点都为Follower。当客户端Client连接到ZooKeeper集群中任何一个节点执行写请求时,这些请求都会被发送到Leader节点上,然后Leader节点上数据变更会同步到集群中其他的Follower节点。

Leader节点在接收到数据变更请求后,首先将变更写入本地磁盘,以作恢复之用。当所有的写请求持久化到磁盘以后,才会将变更应用到内存中。

ZooKeeper使用了一种自定义的原子消息协议,在消息层的这种原子特性,保证了整个协调系统中的节点数据或状态的一致性。Follower基于这种消息协议能够保证本地的ZooKeeper数据与Leader节点同步,然后基于本地的存储来独立地对外提供服务。

当一个Leader节点发生故障失效时,消息层负责重新选择一个Leader,继续作为协调服务集群的中心。

zookeeper-001

公司直接应用Zookeeper的场景并不多,主要用到它的leader选举和znode监视两个特性。

  • leader选举应用场景:

在做pgxl集群高可用时编写了gtm和datanode自动failover的监听脚本。为了确保脚本正常运行,将其部署在由3个Zookeeper组成的zk集群中,pgxc_ctl.conf文件由zk集群保证一致性,脚本的执行者由zk的leader选举产生,只有master是唯一的脚本执行者。

  • znode监视应用场景:

游戏服务端的web应用集群中存在一些常用的配置项,这些配置项是在各个web应用初始化时从mysql读取缓存到各自内存中。为了保持同步更新,各web应用监听zk集群的一组znode,当mysql数据提交并验证通过后,通过修改相关znode,使各web应用监听到变化,从mysql中读取相关配置项更新到内存中。

Zookeeper集群搭建(zookeeper-3.4.6)

三台主机:
172.16.0.3 node1
172.16.0.4 node2
172.16.0.5 node3
操作系统:CentOS7

  • 各节点新建用户zookeeper。
useradd zookeeper
  • 选择其中一个节点安装和配置zookeeper。

解压zookeeper-3.4.6.tar.gz到/opt/下

cd /opt
tar zxvf zookeeper-3.4.6.tar.gz
cd zookeeper-3.4.6

修改conf/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=/data1/zookeeper/data
# the port at which the clients will connect
clientPort=2181
# 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=node1:2888:3888
server.2=node2:2888:3888
server.3=node3:2888:3888

修改log4j.properties文件以下属性

zookeeper.log.dir=/data1/zookeeper/log
zookeeper.tracelog.dir=/data1/zookeeper/log

# Max log file size of 10MB
log4j.appender.ROLLINGFILE.MaxFileSize=10MB
# uncomment the next line to limit number of backup files
log4j.appender.ROLLINGFILE.MaxBackupIndex=10

修改bin/zkEnv.sh文件,设置out日志目录

# 在文件最上面增加以下两个变量
ZOO_LOG_DIR=/data1/zookeeper/log
ZOO_LOG4J_PROP="INFO,ROLLINGFILE"
  • 将上面安装配置后的Zookeeper分发到其他节点。
cd /opt
scp -r zookeeper-3.4.6/ zookeeper@node2:/opt
scp -r zookeeper-3.4.6/ zookeeper@node3:/opt
  • 各节点分别设置myid。

在zoo.cfg的配置项dataDir指定的目录下创建myid文件,里面的内容是一个用来标识当前主机的数字,与zoo.cfg中的server.*对应

# 在node1执行
echo "1" > /home/hadoop/storage/zookeeper/myid
# 在node2执行
echo "2" > /home/hadoop/storage/zookeeper/myid
# 在node3执行
echo "3" > /home/hadoop/storage/zookeeper/myid
  • 启动Zookeeper集群。
# 各节点分别执行
/opt/zookeeper-3.4.6/bin/zkServer.sh start
tail -500f /data1/zookeeper/log/zookeeper.out

基本操作和注意事项

shell操作。

# 查看节点状态,Leader or Follower
/opt/zookeeper-3.4.6/bin/zkServer.sh status
# 启动停止Zookeeper
/opt/zookeeper-3.4.6/bin/zkServer.sh start
/opt/zookeeper-3.4.6/bin/zkServer.sh stop
# 通过自带zkCli连接zkServer集群
/opt/zookeeper-3.4.6/bin/zkCli.sh -server node1:2181
/opt/zookeeper-3.4.6/bin/zkCli.sh -server node1:2181,node2:2181
/opt/zookeeper-3.4.6/bin/zkCli.sh -server node2:2181,node1:2181/some_znode

# zkCli进入shell后:
# 创建znode
create /zk_conf abcde
create /zk_conf2 null
# znode赋值取值
set /zk_conf kkk
get /zk_conf
# 无论是交互还是通过其他方式执行zkshell,结束后都要quit
quit

#其他方式执行zkshell
sh /opt/zookeeper-3.4.6/bin/zkCli.sh -server node1:2181 << EOF 2>/dev/null 
  get /zk_conf2
  quit
EOF

echo "create /my_version null" >> /tmp/tmpzksh.info
echo "set /my_version blablabla" >> /tmp/tmpzksh.info
echo "quit" >> /tmp/tmpzksh.info
/opt/zookeeper-3.4.6/bin/zkCli.sh -server node1:2181 < /tmp/tmpzksh.info

Zookeeper的znode的内容只能是字符串,且需要特殊处理空格、换行等。

怎样通过shell将文件内容存入znode?

# 先xxd -p转码,替换换行符,开头处拼接zk命令如set /zk_conf ,输出到临时文件中
cat /tmp/pgxc_ctl.conf | xxd -p | tr "\n" "\\" > tmpout ;echo "set /zk_conf `cat tmpout`" > tmpout
# 然后执行
/opt/zookeeper-3.4.6/bin/zkCli.sh -server node1:2181 < tmpout

#反向操作,取回该文件内容
/opt/zookeeper-3.4.6/bin/zkCli.sh -server node1:2181 get /zk_conf |tail -n1 |tr "\\" "\n" |xxd -p -r > tmpout2

每个ZNode只存放少量的同步数据,一般不超过1M,否则会影响性能。

ZooKeeper中的Watch是只能触发一次,触发后想要继续监听需要再次设置watch。

客户端连接到ZooKeeper Server以后,会维护一个TCP连接,设置watch后如果连接断开则不能收到znode数据变更通知。

Zookeeper自带的zkclient功能很原始,通常使用封装后的java工具Curator进行操作。

参考
http://shiyanjun.cn/archives/469.html
http://shiyanjun.cn/archives/474.html
http://shiyanjun.cn/archives/492.html

Creative Commons License

本文基于署名-非商业性使用-相同方式共享 4.0许可协议发布,欢迎转载、使用、重新发布,但请保留文章署名wanghengbin(包含链接:https://wanghengbin.com),不得用于商业目的,基于本文修改后的作品请以相同的许可发布。

发表评论