Zookeeper的相关思考
相信大部分同学第一次接触到ZooKeeper(后文中简称为zk)都是和Dubbo一起接触到的,在Dubbo开源时将阿里内部的注册中心进行剥离,用zk作为服务发现的注册中心进行使用的。在大规模的微服务化一段时间后,有越来越多的声音提醒我们zk并不适用于作为服务发现的注册中心进行使用。从下面三个问题出发,探寻一下zk为什么不适用作为注册中心。
- zk是什么,以及由来和想要解决的问题?
- zk为什么不适用作为注册中心?
- zk迁移eurka的方案
zk的由来
- 维基百科的简介
Apache ZooKeeper是Apache软件基金会的一个软件项目,它为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。ZooKeeper曾经是Hadoop的一个子项目,但现在是一个独立的顶级项目。
- zk的由来
下面这段内容摘自《从Paxos到Zookeeper 》 ,本文中很多的名词介绍也来自本书。
Zookeeper 最早起源于雅虎研究院的一个研究小组。
在当时,研究人员发现,在雅虎内部很多大型系统基本都需要依赖一个类似的系统来进行分布式协调,但是这些系统往往都存在分布式单点问题。
所以,雅虎的开发人员就试图开发一个通用的无单点问题的分布式协调框架,以便让开发人员将精力集中在处理业务逻辑上。
关于“ZooKeeper”这个项目的名字,其实也有一段趣闻。在立项初期,考虑到之前内部很多项目都是使用动物的名字来命名的(例如著名的Pig项目),雅虎的工程师希望给这个项目也取一个动物的名字。
时任研究院的首席科学家 RaghuRamakrishnan 开玩笑地说:“在这样下去,我们这儿就变成动物园了!”
此话一出,大家纷纷表示就叫动物园管理员吧一一一因为各个以动物命名的分布式组件放在一起,雅虎的整个分布式系统看上去就像一个大型的动物园了
而 Zookeeper 正好要用来进行分布式环境的协调一一于是,Zookeeper 的名字也就由此诞生了。
zk的诞生是为了解决在分布式环境下不同系统之间进行分布式协调的场景。在分布式环境下需要将同一个系统分布式化后对外提供出像一个系统一样的服务,这样就需要引入分布式协调工具,将这种原来是由应用系统解决的事情剥离开的工具。因此zk就诞生了。
总的来说,zk提供了一个可靠的分布式的工具,可以对外提供一下几种功能(API中的方法):
- 创建节点
- 读节点数据
- 更新节点数据
- 删除节点
- 监控节点变化
- zk解决的问题
- 元数据配置:kafka中存储元数据
- 注册中心:应用于充当注册中心
- 作为分布式锁:Curator分布式锁
zk不适用作为注册中心
网上大部分都在说zk不适合作为注册中心其根据主要是 Eureka! Why You Shouldn’t Use ZooKeeper for Service Discovery一文,分析其原因主要是说zk是基于cp的,而注册中心的业务更适用于ap。
下面根据阿里巴巴为什么不用 ZooKeeper 做服务发现一文整理而来
数据的一致性需求分析
注册中心最本质的功能就是一个Query函数Si = F(service-name),以service-name作为查询参数,返回服务对应的地址;
如果注册中心满足ap的情况:
每次返回的结果都不一样,这样会导致不同的服务提供者接收到的流量都不一样,在短时间内流量的不一致会因为多次调用根据大数理论这点流量差异会被抹消掉。
如果注册中心是基于cp的情况:
在不保证可用性的情况下,如果一个zk节点与leader节点失联的情况下为了保证zk中数据的一致性,该节点不会对外提供服务。
对于和该zk节点在同一分区中的服务来说,由于zk的异常导致本身业务也不能进行同区调用是不能接受的。可以说在实践中,注册中心不能因为自身的任何原因破坏服务之间本身的可连通性,这是注册中心设计应该遵循的铁律!
在 CAP 的权衡中,注册中心的可用性比数据强一致性更宝贵,所以整体设计更应该偏向 AP,而非 CP,数据不一致在可接受范围,而P下舍弃A却完全违反了注册中心不能因为自身的任何原因破坏服务本身的可连通性的原则。
ps:总的来说就是注册中心在面临CAP的问题上,可以接受数据的不一致,但是不能接受业务的不可用。
服务规模、容量、服务联通性
从服务的规模、容量、服务联通性来分析
由于zk为了保证数据的一致性,因此在进行写入的时候必须又Leader发起,在向其他节点分发写入操作,因此写入操作不能进行横向扩展。这样就无法解决zk的服务规模增长问题,或者将注册节点根据业务进行划分,不同的业务注册到不同的zk上去,但是注册中心作为基础服务,不能由于自身的限制去影响业务,让业务按照业务服务进行划分。
注册中心需要持久存储和事务日志
注册中心需要进行持久化存储和事务日志嘛?我认为是需要的,但是不用像zk一样把每一次变更的日志记录下来。
例如:
-
serviceA=》{ip1:0001,ip1:0002}
-
serviceA=》{ip1:0001}
-
serviceA=》{ip1:0001,ip1:0002}
这样的ABA的持久化连续记录,对于服务的调用方来说并没有什么意义,服务调用发起方更关注的是其要调用的服务的实时的地址列表和实时健康状态,每次发起调用时,并不关心要调用的服务的历史服务地址列表、过去的健康状态。
需要进行持久化记录的应该是服务的元数据信息:服务的版本,分组,所在的数据中心,权重,鉴权策略信息,service label等
Service Health Check
使用zk作为服务注册中心时,服务的健康监测是用Zookeeper的Seesion机制可以理解为绑定TCP长连接的监测。这种监测只是能证明client的网络通路是畅通的,并不能代变服务是可用。
健康检测的一大基本设计原则就是尽可能真实的反馈服务本身的真实健康状态,否则一个不敢被服务调用者相信的健康状态判定结果还不如没有健康检测。
注册中心的容灾考虑
在实践中,注册中心不能因为自身的任何原因破坏服务之间本身的可连通性,这句话说的是就算zk服务宕机的情况下也不能影响已有服务的功能。zk的client端并没有提供这样的功能,dubbo使用zk作为注册中心时候的时候,是在dubbo消费者缓存了生产者的地址。
阿里对于zk的总结
The King Of Coordination for Big Data!
在粗粒度分布式锁,分布式选主,主备高可用切换等不需要高TPS 支持的场景下有不可替代的作用,
而这些需求往往多集中在大数据、离线任务等相关的业务领域,因为大数据领域,讲究分割数据集,
并且大部分时间分任务多进程/线程并行处理这些数据集,但是总是有一些点上需要将这些任务和进程统一协调,
这时候就是 ZooKeeper 发挥巨大作用的用武之地。
但是在交易场景交易链路上,在主业务数据存取,大规模服务发现、大规模健康监测等方面有天然的短板,应该竭力避免在这些场
景下引入 ZooKeeper,在阿里巴巴的生产实践中,应用对ZooKeeper申请使用的时候要进行严格的场景、容量、SLA需求的评估。
所以可以使用 ZooKeeper,但是大数据请向左,而交易则向右,分布式协调向左,服务发现向右。
总结
zk在业务领域作为服务发现的注册中心是越来越不适用了,在以前没有专门的工具的情况下,一个可靠、易用的工具就是作为服务发现的最好选择,但是在当下zk作为注册中心确显得不合适宜。目前注册中心的选择有很多