大致来说,zookeeper 的使用场景如下:
- 分布式协调
- 分布式锁
- 配置管理
- HA高可用性
- 负载均衡
- 命名服务
一、分布式协调
这个其实是 zookeeper 很经典的一个用法,简单来说,就好比,你 A 系统发送个请求到 mq,然后 B 系统消息消费之后处理了。那 A 系统如何知道 B 系统的处理结果?用 zookeeper 就可以实现分布式系统之间的协调工作。A 系统发送请求之后可以在 zookeeper 上对某个节点的值注册个监听器,一旦 B 系统处理完了就修改 zookeeper 那个节点的值,A 系统立马就可以收到通知,完美解决。

二、分布式锁
举个栗子。对某一个数据连续发出两个修改操作,两台机器同时收到了请求,但是只能一台机器先执行完另外一个机器再执行。那么此时就可以使用 zookeeper 分布式锁,一个机器接收到了请求之后先获取 zookeeper 上的一把分布式锁,就是可以去创建一个 znode,接着执行操作;然后另外一个机器也尝试去创建那个 znode,结果发现自己创建不了,因为被别人创建了,那只能等着,等第一个机器执行完了自己再执行。

三、配置管理
zookeeper 可以用作很多系统的配置信息的管理,比如 kafka、storm 等等很多分布式系统都会选用 zookeeper 来做一些元数据、配置信息的管理,包括 dubbo 注册中心也支持 zookeeper 。
将数据信息发布到一个或者多个ZK节点上,应用程序监听这些节点当有数据变化时就获取这些变化并应用到程序中,实现动态更新配置的功能。发布订阅中通常有推拉两种模式,ZK采用推拉结合,客户端注册感兴趣的节点,一旦节点发生变化服务器会发出Watcher事件通知(推),然后客户端收到消息后主动去服务器提取变化(拉)。
这种配置管理通常应用在具有配置通用性的场景中,比如机器列表、某些参数的开关或者数据库配置信息等。
-
这些信息通常体量小
-
在应用运行时会随时调整
-
这些应用(至少是某一组应用)都使用相同的配置
常规解决办法是本地配置文件或者内存变量(通过JMX方式对正在运行的JAVA程序进行修改)。这些常规办法在集群规模较小的时候比较方便但是集群规模一大管理就比较困难。
比如数据库配置信息变化
-
首先在ZK上创建一个节点叫做 /Configuration 这里面有一个APP名称节点表示特定APP,这个APP名称节点下面有一个叫做 dbConfig的节点用于存储数据库配置信息(/Configuration-->APP1-->dbConfig)
-
然后将配置信息写入到这个节点(这些信息肯定是序列化后写入的,如果在程序中不是以对象形式存在也可以不用序列化)
-
应用程序启动后读取这个节点数据,然后在这个节点上注册一个Watcher事件,当数据有变化时再次读取该节点数据并应用到自己的程序上。
四、HA高可用性
这个应该是很常见的,比如 hadoop、hdfs、yarn 等很多大数据系统,都选择基于 zookeeper 来开发 HA 高可用机制,就是一个重要进程一般会做主备两个,主进程挂了立马通过 zookeeper 感知到切换到备用进程。

五、负载均衡
ZK提供的负载属于软负载均衡服务。通常的做法就是动态的DNS服务,如果你的机器数量比较少你可以手动在内网DNS上配置这些域名,一个域名对应一个IP。如果集群规模比较大手动维护这些信息相当繁琐;另外你还可以采用HOST的方式就是在服务器上配置本地HOST把这些域名写进去,还是一样的问题规模小传统方式都很好用,但是规模大尤其是有时候需要动态扩容或者缩容的时候你再去手动维护这些HOST或者DNS记录显然就不能满足业务需求。
在Zookeeper中如何解决呢?下面的名称就是名字不一定你也这样取,毕竟节点名称是自定义的。
-
首先建立一个节点叫做 /DDNS 这下面包含所有应用的名字比如APP1,APP2等,每个应用名字节点下面又一个域名比如 app1.servers.abc.com这样一个域名(/DDNS-->APP1-->app1.servers.abc.com)后面这个域名就是改APP1集群使用的,这个节点包含的数据可以是IP:PORT或者多个IP:PORT,看下图

-
应用读取节点数据获取IP列表,然后根据负载均衡算法找到一个IP来使用,之后注册一个监听事件来监听该节点的变化
-
IP变更我们只需要在该节点进行操作就可以
上面的过程还是需要人工干预,如何改进一下呢?可以划分几个组件出来
-
Register,负载域名动态注册的服务,这个服务可以是单台但最好是一个集群,服务提供者通过SDK向Register注册,也就是把服务提供者所使用域名和IP:PORT发给Register,它再获取ZK集群节点数据,加上本次注册的数据,产生一个新数据更新到ZK节点上
-
Dispatcher,负载域名解析,通过域名向该服务查询获取IP:PORT列表,它监听ZK节点发生有变化之后就更新存储在自己内存中的信息,相当于域名使用者不直接去ZK节点读取数据。同时它还提供屏蔽功能,也就是说服务提供者都可用但是我可以设置只解析出部分服务提供者IP:PORT出来。
-
Scanner,负载检查维护服务状态,它作用是检查服务提供者的可用性,这里采用服务提供者主动汇报自身状态的方式,这种状态可以包括很多信息服务是否可用、当前QPS、RT、JVM的资源状态等。Scanner会记录服务提供者每一次的状态。如果一段时间后(通常为几秒)发现有服务提供者没有汇报,那么就认为不可用,然后去更新ZK节点,把失败的IP:PORT信息删除。
-
Monitor,负载监控DDNS系统本身的状态。
-
Controller,是一个DDNS的后台管理端,负载管理上述组件以及必要时候的手工干预。
-
SDK,服务提供者和消费者通过封装的SDK来和上述组件通信。
六、命名服务
命名服务是分布式系统中的基本功能之一。被命名的实体通常可以是集群中的机器、提供的服务地址或者远程对象,这些都可以称作为名字。常见的就是一些分布式服务框架(RPC、RMI)中的服务地址列表,通过使用名称服务客户端可以获取资源的实体、服务地址和提供者信息。命名服务就是通过一个资源引用的方式来实现对资源的定位和使用。在分布式环境中,上层应用仅仅需要一个全局唯一名称,就像数据库中的主键。
zookeeper的命名服务功能主要是根据指定名字来获取资源或服务的地址,提供者等信息,利用其znode的特点和watcher机制,将其作为动态注册和获取服务信息的配置中心,统一管理服务名称和其对应的服务器列表信息,我们能够近乎实时地感知到后端服务器的状态(上线、下线、宕机)。
在Zookeeper中通过创建顺序节点就可以实现。你创建的时候只需要提供节点名称,至于序号它自己会返回一个。你每次使用的语句是相同的,但是由于顺序节点的特性它返回的内容不同但是是有顺序的。那么你通过 type1-job00000000 这种就可以得到一个唯一ID。

本文介绍了Zookeeper的使用场景,包括分布式协调,可实现系统间协调;分布式锁,保证操作顺序;配置管理,用于管理系统配置信息;HA高可用性,实现主备进程切换;负载均衡,提供软负载均衡服务;还有命名服务,可动态注册和获取服务信息。
1520

被折叠的 条评论
为什么被折叠?



