Zookeeper概述
前言:本文仅对Zookeeper中的一些基本概念进行讲解,适合对Zookeeper不了解的新人,并不对例如Zookeeper怎么选举,怎么实现分布式锁,写入过程是怎么二阶段提交的,这类细节问题作者将在其他Zookeeper文章中进行讲解。
1.什么是zookeeper
一个高性能、高可用的开源分布式协调服务,
2.Zookeeper能做什么
1.统一配置管理、2.统一命名服务、3.分布式锁、4.集群管理。
3.Zookeeper的核心
3.1文件系统:
zookeeper的数据结构类似Unix的目录树文件结构,每个节点叫做Znode,可用理解为一个文件夹,根目录为/
对应到文件系统中就是:
/
/java
/继承
/封装
/多态
/c++
Zookeeper的节点分为两种:
持久节点:持久节点顾名思义,就是只要创建后客户端没有手动删除,就会一直存在
临时节点:生命周期与客户端会话相同,客户端连接断开或失效后,节点自动删除
注意:Zookeeper虽然提供了一个类似文件系统的数据结构,且实现了数据存储的功能,但Zookeeper的本意并不是提供一个分布式存储系统,而是通过这个数据结构来实现它的协调服务,所以每个Znode的大小被限制为小于1M。
3.2.监听机制:
监听机制,就是Zookeeper的灵魂所在,Zookeeper的所有功能都是通过它的监听机制来实现的,通俗来讲,就是让客户端监听某个节点的变化,当这个节点发生变化时,Zookeeper会立刻通知所有监听该节点的客户端,通过这个简单机制,你就可以使用Zookeeper拓展出无限种可能。
例1:分布式配置中心:
方案一:Zookeeper实现,如上图所示,此时你有一个3台Zookeeper组成的Zookeeper集群,这个集群对外提供的是同一个Zookeeper服务,此时你有三个客户端A、B、C,而在Zookeeper中有个节点/config其中存储着一些系统中的常用配置,这时候你只要让ABC三个节点都去监听/config这个节点的变化,则当/config中的数据发生变化时,会立刻通知ABC三个客户端,这样客户端就能立即获得最新的配置文件,而且只需要修改一次配置文件,大大简化了分布式配置中心。
方案二:本地配置文件,如果不通过Zookepper,则三台节点需要分别维护一个自己的配置文件,尽管这是三份完全一样的文件,而当某个配置项需要发生改动时,则需要分别修改三份配置文件。
这个例子很好的展示了Zookeeper的两大特性:文件系统、监听机制,首先配置信息需要一个存储介质,Zookeeper就提供了很好的服务,其实,配置信息发生改变的时候,需要所有节点都能获取这个变化,此时监听机制就起到了决定性的作用,所用节点能立刻获取/config节点的变化,并获取最新的配置信息。
优劣对比:
方案二:当你的集群数量不多时,显然方案二实现起来会更加方便,因为配置文件本身就不会频繁的发生改变,一次就改几个文件也在可接受范围内,最重要的是你的系统也不需要额外维护一个Zookeeper集群,虽然Zookeeper本身就是一个高可靠的集群,但依然不排除故障的可能性,显然这对你系统的健壮性是不利的,会给你原本稳定的系统带来不确定性。
方案一:当你的集群数量足够大时,例如有几百上千台,这时一台台的修改配置文件显然不现实,而且一般当你维护着一个庞大的分布式集群时,往往也同时维护着一个Zookeeper集群,来提供分布式锁或集群管理服务,所以此时往往并不需要你单独维护一个Zookeeper集群来作为配置中心,而是使用原先的Zookeeper来为你新的业务提供服务,所以并不会对你的系统产生侵入性。
3.3过半通过:
1.过半投票选举Leader,获得半数以上投票的Follower会升级为Leader,之后所有启动的Follower自动变成Follower且追随Leader
2.过半写入commit确认,数据才会真正写入,所有写请求需要半数以上节点commit后,Leader才会认为数据写入成功,并可以可读取到
4.Zookeeper集群角色
Leader:需要所有Follower投票选出,负责维护 Follwer 及和Observer的心跳,只有Leader有写的权限,Follower和Observer也可以接受写请求,但是需要转发给Leader,再由Leader分发到其他Follower和Observer
Follower:可以接受客户端的读写请求,读请求会立即返回结果,但写请求需要转发给Leader,读取实时结果可能跟Leader最新结果有出入,可能Leader已经确认写入某一值,但该Follower还未收到Leader的写确认,可通过sync path命令让Follower强制与Leader同步数据,会增加请求响应时间,但保证了数据的一致性。
Observer:功能与 Follower 类似,但是不参与投票,只接受请求,主要是为了提高Zookeeper集群的读取能力,写请求同样转发给Leader,一个Zookeeper集群中通常Leader+Follower只有5个,其余的都为Observer
5.为什么Zookeeper集群建议节点数为奇数?
首先从集群的可靠性讲:我们知道Zookeeper的选举和事务机制是需要过半投票的,也就是票数需要大于 集群数量/2 ,由此可知当集群数量为3时,需要2票通过,而集群数量为4时,需要3票通过。注意,这里说的大于1/2是说的集群启动时数量的1/2,而不是剩余存活数量的1/2,有的新手会将这两个概念搞混,如果你的集群数量是4,则当挂了一台以后,你的集群数量还是4,只是有一台是宕机状态,所以同样需要3票通过,而不是变成3台集群,2票通过。
由此可知,3台机器和4台机器,容错率是相同,都是允许宕机一台,当宕机两台后,集群将会变成不可用,所以4台机器并没有提高集群的可靠性,反而降低了集群的写性能,因为Zookeeper集群在处理写请求时,是需要过半写入提交,才会认为写入成功,而4机器需要3台确认写入,而3台机器只需要两台确认,所以四台就会使Leader多处理一次网络IO,降低了写入的效率。
下图是Zookeeper官方给出的910个客户端下,集群数量和读写请求占比对应的吞吐量关系图,X轴是读请求占的百分比,Y轴是可以负载的请求量。可以明显看出来的是,读请求占比越高,Zookeeper可以承担的负载量越大。而写请求占比大时,机器数量越少,负载量越大,由此可以验证我门刚刚的结论,4台机器比三台机器写入更慢,而可靠性不变,所以建议集群节点数为奇数。
而且,Zookeeper官方建议,Zookeeper尽量多用来读取,而不是频繁的写入,由上图可以看出,当读写比例为2:8或1:9时,Zookeeper的吞吐量非常高,几乎呈指数级上升,而且机器数量为5台或7台时就有很高的性能,并且节省资源。
注意:以上所有关于机器数量的讨论,均不包括Observer,Observer只为集群提供接受请求的能力,不参与投票,所以不会拉低Zookeeper集群的写入性能。
结论:Zookeeper集群尽量以奇数,5台或7台为最优,需要提高Zookeeper的吞吐量时,优先考虑增加Observer的数量。
会拉低Zookeeper集群的写入性能。
结论:Zookeeper集群尽量以奇数,5台或7台为最优,需要提高Zookeeper的吞吐量时,优先考虑增加Observer的数量。
如果觉得文章对你有帮助的话,可以微信关注我的公众号:码农小诚
关注我的公众号更多技术文章分享实时更新,与你共同成长,回复【555】还有55本java技术书籍,免费送,回复【zk】还能获取更多zookeeper相关技术书籍。
关注博主公众号,后续为你带来更多Zookeeper小技巧