1.什么是zookeeper?
zookeeper是apache公司开源的分布式协调服务,整个服务是由多台结点服务器构成。用户通过zookeeper的java客户端与zookeeper交互。zookeeper并没有在服务器端实现任何的分布式同步服务,只提供了一个解决分布式同步的原语集,以便用户自己根据业务来实现分布式同步问题,比如分布式锁,分布式选举等问题。
2.zookeeper特点
- zookeeper本身也是一个分布式形式存在,集群中建议使用奇数台服务器搭建,比如3,5,7台服务器搭建分zookeeper集群。
- zookeeper集群中任何一个follower结点都能响应读请求。而写请求必须由leader结点处理。
- zookeeper将数据全部存储到内存中,读效率很高。但是由于内存限制,不便于储存大量数据。
- 顺序一致性:保证客户端的请求有序进行。
- 原子性:保证客户端的请求在每个结点上的原子性,要么成功执行该事务,要么都执行失败。
- 单一视图:集群中的每个结点的数据模型都一致的,对于用户而已视图是一样的。
- 数据最终一致性:不保证数据实时一致,允许分布式数据经过一个时间窗口达到最终一致。
3.zookeeper的应用场景
- 配置中心
在一个web项目中,会涉及到很多的配置文件,比如mysql的,redis,springmvc的。这些配置文件一般都是公用的。在zookeeper之前,开发中都是通过写配置文件将配置信息存储在项目中,然后项目启动时候去加载配置文件。但是随着项目不断的增多,每个项目都需要这么一份或者多份配置文件,就显得太冗余了。而且,如果有个配置文件需要更改,比如mysql数据库连接用户和密码。那么我们需要更改配置文件之后重新打包发布工程,这样浪费了很多时间。而有了zookeeper之后就可以实现配置的集中管理。我们只需要在zookeeper中建立配置文件对应的永久性结点,如果项目启动需要初始化配置的时候就去zookeeper里面获取。如果在这些结点上添加watcher事件,每次该节点有变动就会去通知监听这个结点的客户端,这样一来就可以实时修改配置文件的结点,而且不用重新部署,重新启动工程了。
默认前提是:数据量很小,但是数据更新可能会比较快的场景。
- 分布式锁
分布式锁是控制分布式系统之间同步访问共享资源的一种方式。如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源,那么访问这些资源的时候,往往需要通过一些互斥手段来防止彼此之间的干扰,以保证一致性,在这种情况下,就需要使用分布式锁了。比如:通常的做法是把zk上的一个znode看作是一把锁,通过create znode的方式来实现。所有客户端都去创建 /distribute_lock 节点,最终成功创建的那个客户端也即拥有了这把锁。所有视图来获取这个锁的客户端,最终都是会被安排执行,只是有个全局时序了。做法和上面基本类似,只是这里 /distribute_lock 已经预先存在,客户端在它下面创建临时有序节点(这个可以通过节点的属性控制:CreateMode.EPHEMERAL_SEQUENTIAL来指定)。Zk的父节点(/distribute_lock)维持一份sequence,保证子节点创建的时序性,从而也形成了每个客户端的全局时序。 - leader选举
利用ZooKeeper的强一致性,能够保证在分布式高并发情况下节点创建的全局唯一性,即:同时有多个客户端请求创建 /currentMaster 节点,最终一定只有一个客户端请求能够创建成功。利用这个特性,就能很轻易的在分布式环境中进行集群选取了。比如:所有客户端创建请求,最终只有一个能够创建成功。在这里稍微变化下,就是允许所有请求都能够创建成功,但是得有个创建顺序,于是所有的请求最终在ZK上创建结果的一种可能情况是这样: /currentMaster/{sessionId}-1 ,/currentMaster/{sessionId}-2,/currentMaster/{sessionId}-3 ….. 每次选取序列号最小的那个机器作为Master,如果这个机器挂了,由于他创建的节点会马上小时,那么之后最小的那个机器就是Master了。 - 发布/订阅
ZooKeeper中特有watcher注册与异步通知机制,能够很好的协调分布式环境下数据实时更新的同步问题。比如在同一个结点注册watcher监听,一旦分布式环境下有一台服务器对该结点做了变更,其他监听该结点的服务器就得知变化,并对变化及时处理。 - 命名服务
在分布式环境中,通过使用命名服务,客户端能够通过指定的名字来获取服务提供者的地址或者信息。简单来说使用Zookeeper做命名服务就是用路径作为名字,路径上的数据就是其名字指向的实体。比如阿里巴巴的dubbo就是使用zookeeper作为命名服务的:
服务提供者在启动的时候,向zk指定路径/dubbo/${serviceName}/providers文件夹下写入自己的URL地址,这个操作就完毕了服务的公布。
服务消费者在启动的时候回,订阅/dubbo/{serviceName}/providers文件夹下的提供者URL地址, 并向/dubbo/{serviceName} /consumers文件夹下写入自己的URL地址。注意,全部向ZK上注冊的地址都是暂时节点。这样就行保证服务提供者和消费者可以自己主动感应资源的变化。
网友评论