1、Zookeeper是什么
Zookeeper是Apache Software Foundation下的分布式、开源项目,通过java实现,提供java和c两个版本的api。分布式应用可以基于它提供的一系列基础服务来方便的实现配置管理、集群管理、分布式锁等服务。所以说官网定义Zookeeper是一个coordination service。
2、基本特性
简单:Zookeeper允许分布式应用通过共享的、多层级的命名空间来彼此协调,这个命名空间类似于传统的文件管理系统,不同之处在于这个层级命名空间是保存在内存里的,而不是存储在磁盘上。Zookeeper非常重视高性能和高可用,并且严格遵循顺序一致性(严格的排序意味着可以在客户端实现复杂的同步原语)
基于多副本:就跟大多数分布式应用一样,Zookeeper也会在集群里保留多个数据副本。提供服务的节点必须感知到其他节点的存在。每个节点在内存里存储一份状态镜像,并且维护一份事物日志快照,存储在磁盘里。只要集群大部分节点可用(超过二分之一),那么整个集群就是可用的。
有序性:Zookeeper通过给每个更新操作提供一个序号来记录操作顺序,后续操作可以使用该顺序来实现更高级别的抽象,例如同步原语.Zookeeper保证对同一个数据的更新顺序和客户端发送更新操作的顺序保持一致。并且更新结果要么是成功,要么是失败,不存在中间状态。客户端不管连接的是集群哪个节点,看到的视图都是一致的
快速:对于读密集的服务,Zookeeper是能发挥很大的性能的,尤其是读写比例超过10:1的场景。
3、Zookeeper解决什么问题
配置管理:当一个服务本身节点以及涉及的配置比较少,并且不需要经常变换的时候,可以直接将配置写在本地,当需要变更时直接改文件然后发布变更即可。但是当你的配置很多(静态页链接、db、中间件、开关、版本、路由等),服务本身涉及到几十上百个节点,配置经常需要变更(比如各种开关),那么为了能够对配置进行动态管理,并且保持节点配置统一,则可以使用Zookeeper进行集中配置动态管理
分布式锁:当一个分布式应用里某些服务(比如job)同一时间只能被某一个节点调用时,通常的做法是可以给db加锁,或者在服务里通过判断指定某个节点执行。db加锁的话会降低读写效率,并且通常需要考虑各种异常情况。而通过指定某个节点执行,在节点异常的情况下,会导致服务挂掉,无法发挥出分布式应用的优势,这时候可以利用Zookeeper分布式锁来实现(选主、调度),在保证互斥的前提下,动态对分布式应用所有节点进行调度。
集群管理:在一个分布式应用里,某些节点因为各种问题无法提供服务,或者在特定场景下进行扩容,集群中的节点如何动态感知这些变化呢?通过传统的dns服务可以实现,但是需要解决缓存问题,通过变更Proxy配置也可以实现,但是需要手动维护,也可以通过消息订阅等方式来实现,还可以通过自己实现注册中心来完成,但是实现成本比较高。可以通过Zookeeper进行集群管理,Alibaba开源的SOA框架Dubbo就采用了Zookeeper作为服务发现的底层机制。
4、Zookeeper涉及到的基本概念
基于多层命名空间的数据模型:Data model and the hierarchical namespace
命名空间和文件系统类似,一个name是由一系列通过/分割的路径组成。存储在此name下的节点数据(此节点代表数据节点,而不是集群节点)是通过这个路径来辨别。
节点和临时节点:Nodes and ephemeral nodes
和文件系统不同,每个数据节点除了创建子节点,还能可以存储数据。这些数据一般是用于提供协调服务的,比如某种状态、配置、地址等信息,因此数据大小一般不会很大,最好是不超过kb级别。文章后面会使用znode来代表数据节点。
为了便于提供原子访问和有序更新,znode需要存储更改数据的版本序号,ACL授权信息和时间戳等信息。数据的存取都是原子性的。读写操作都是通过一定的acl规则来获取或者更改znode里所有的信息。Zookeeper还提供临时znode,此znode会随着session的失效而删除。
更新事件监听器:Conditional updates and watches
Zookeeper提供监听器机制,客户端可以在znode上添加监听器,当znode发生变化的时候,添加在它上面的监听器会被触发,然后删除,当监听器被触发后,客户端会受到一条znode变更的通信包,
5、基本API操作:
create:创建一个znode
delete:删除一个znode
exists:判断znode是否存在
get data:从znode获取数据
set data:更新znode数据
get children:获取znode的子节点
sync:等待数据处理完毕
6、Zookeeper安装:已在centos 6.5安装zookeeper-3.4.8为例子
安装java: yum install java -y
下载zookeeper :https://zookeeper.apache.org/
解压:tar -xvf zookeeper-3.4.8.tar -C /usr/local/
创建数据文件夹:mkdir -p /usr/local/zookeeper-3.4.8/data
在数据文件夹/usr/local/zookeeper-3.4.8/data下创建myid,并且写入一个整数,此整数代表节点在集群中的唯一序号,可以从1开始,多台机器依次递增,比如第一个节点写1
在/usr/local/zookeeper-3.4.8/conf 下创建zoo.cfg,并写入集群中节点配置,比如:server.序号保持myid中的值一致
server.1=10.80.1.10:2888:3888
server.2=10.80.1.11:2888:3888
server.3=10.80.1.12:2888:3888
创建log文件夹:mkdir /usr/local/zookeeper-3.4.8/log
增加log和data配置:编辑zoo.conf,写入配置:
dataDir=/usr/local/zookeeper-3.4.8/data
dataLogDir=/usr/local/zookeeper-3.4.8/log
启动节点:
cd /usr/local/zookeeper-3.4.8/bin
./zkServer.sh start
如果启动报错了,则到/usr/local/zookeeper-3.4.8/log去看下启动日志
校验状态:./zkServer.sh status
7、Zookeeper基本维护
扩容:
按照上面那一步配置好zookeeper,并且在zoo.conf下增加新节点的server配置,比如新增了两个节点,则将新节点配置改成如下:
server.1=10.80.1.10:2888:3888
server.2=10.80.1.11:2888:3888
server.3=10.80.1.12:2888:3888
server.4=10.80.1.13:2888:3888
server.5=10.80.1.14:2888:3888
然后依次启动两个新节点。
接着按照myid从小到大的顺序,先将zoo.conf配置改成和上面新节点一直,依次重启旧的follower节点。重启指令cd /usr/local/zookeeper-3.4.8/bin ./zkServer.sh restart ,查看状态是否正常: ./zkServer.sh status
最后将leader节点zoo.conf配置改成和新节点一致,重启,查看状态。
注意事项:
一定要先按照myid从小到大的顺序重启follower节点,重启之前一定不要忘了改配置
一定要最后重启leader节点,重启之前一定不要忘了改配置
缩容
将需要下线的节点按照myid从小到大的顺序停服 ./zkServer.sh stop
将剩下的follower节点按照myid从小到大的顺序,依次更改zoo.conf配置,去掉回收节点的server选项,重启。
最后更改leader节点zoo.conf配置,去掉回收节点的server选项,重启。
注意事项:
一定要先按照myid从小到大的顺序重启follower节点,重启之前一定不要忘了改配置
一定要最后重启leader节点,重启之前一定不要忘了改配置
缩容过程中,一定要保证节点超过半数可用,否则需要几批缩容
8、基本指令:
启动、停止、重启、状态查看
cd /usr/local/zookeeper-3.4.8/bin
./zkServer.sh start
./zkServer.sh stop
./zkServer.sh restart
./zkServer.sh status
清理数据:-n 表示需要保留快照文件数目,默认是保留3个
./zkCleanup.sh -n 50
查看leader节点连接状态:到leader节点执行netstat -ant | grep 3888
查看客户端连接状态:netstat -nat|grep -i '2181'|awk '{print $5}'|awk -F: '{print $1}' | sort -nr | uniq
9、Zookeeper管理工具:
Exhibitor(没有用过,看介绍很实用)
10、参考文章
简介:http://zookeeper.apache.org/doc/current/zookeeperOver.html
数据清理://www.greatytc.com/p/f798aedc776d
11、相关链接:
java api文档:http://zookeeper.apache.org/doc/current/api/index.html