Zookeeper 和 KRaft
这里有一则 Kafka 功能改良的 proposal 书名。要了解去除 ZK 的原因,能细细看看该该文。以下是对该该文的译者。
意图
目前,Kafka 使用 Zookeeper 留存与南区(patitions)、brokers 有关的元数据,以及议会选举 Kafka 驱动器(某一 broker)。他们将去除对 Zookeeper 的倚赖。这样一来,Kafka 在管理工作元数据各方面,将赢得更快的扩展性和精确性,与此同时支持更多的南区。在布署、实用性 Kafka 各方面,也将得到很大的精简。
将元数据视作 Event Log
他们常说将状况作为该事件流管理工作的益处。一个在过程上将叙述消费者位
尽管他们的使用者享用那些便捷,但忽视了 Kafka 本身。他们将作用到元数据的更改看做彼此之间孤立无援,互互相冲突。当驱动器将状况更改通告到软件产业中的其它 broker 时,其它 broker 可能会接到一些更改,但不是全部更改。尽管驱动器会重传数次,但最终会停止重传。这将导致 broker 间处于不并行的状况。
更差劲的是,尽管 Zookeeper 储存 record,但 Zookeeper 中留存的状况经常与驱动器留存在缓存中的状况难以相匹配。例如,当南区 leader 在 Zookeeper 中更改其 ISR(in-sync Replica)时,通常情况下,驱动器会误点几秒才能获知其更改。对于驱动器来说,没有通用型的方法跟踪 Zookeeper 的 event log。尽管驱动器能增设纸制把守,但把守的数量由于性能难题会受限。当促发把守时,把守不负责通告驱动器当前状况,仅仅是通告驱动器状况发生了更改。与此同时,驱动器钟炳昌 znode,然后增设一个捷伊把守,但,从最初把守发出通告,到驱动器完成钟炳昌,重新增设把守期间,状况可能已经产生了捷伊更改。如果不增设把守,驱动器将永远难以获知更改。某些情况下,重新启动驱动器是解决状况不一致的唯一手段。
元数据与储存在独立的系统中,比不上储存在 Kafka 中。此种情况下,驱动器状况与 Zookeeper 状况间和差别有关的难题将荡然无存。与原都通告 broker,比不上让 broker 们从 event log 中消费元数据该事件。这样就保证了元数据更改能够按相同的次序并行到 broker 中。broker 将元数据储存在邻近地区文件中。当那些 broker 重新启动,它们只需要从驱动器中(某一 broker)中加载更改,而无须HMPP加载状况。在此种情况下,他们耗用更慢的 CPU 资源就能赢得更多南区。
精简布署与实用性
Zookeeper 是一套独立的系统,有其实用性文件语法,管理工作工具以及布署模式。这意味着系统管理工作员为了布署 Kafka,需要学习如何管理工作和布署两套独立的分布式系统。这对系统管理工作员来说,是非常艰巨的任务,尤其是在他们不熟悉布署 Java 服务的情况下。统一系统将很大地改善运行 Kafka 的初次体验,并有助于拓宽其应用范围。
由于 Kafka 和 Zookeeper 的实用性文件是分离的,因此极易产生错误。例如,管理工作员在 Kafka 中增设了 SASL(Simple Authentication Security Layer,简单认证安全层),并且错误的认为对所有在网络中传输的数据都做了加密。事实上,还需要在外部系统 Zookeeper 中实用性加密。统一两个系统将赢得完整的加密实用性模型。
最后,未来他们可能需要支持单节点 Kafka 模型。对于那些要测试 Kafka 功能的人来说,无须启动守护进程,将提供很大的便捷性。去除 Zookeeper 倚赖,将使其成为可能。
架构介绍
本 KIP(Kafka Improvement Proposal,Kafka 改良 Proposal) 展现的是一个可扩展的后 Zookeeper 时代的 Kafka 系统的总体愿景。为了突出重要部分,我忽视了大多数细节,比如 RPC 格式、磁盘格式等等。在后续 KIP 中,他们将逐步深入叙述细节。与 KIP-4 类似,提出总体愿景,后续的 KIP 中逐步扩充。
总览
目前,一套 Kafka 软件产业包括几个 broker 节点,Zookeeper 节点作为一套外部 quorum (投票机制,少数服从多数)。他们画了 4 个 broker 节点和 3 个 Zookeeper 节点。这是小软件产业所需的正常配置。驱动器(用橙色标识)在被议会选举后,从 Zoopeeper 的 quorum 中加载其状况。从驱动器连接其它节点的线,在 broker 中代表更新驱动器推送的消息,比如 LeaderAndIsr、UpdateMetadata 消息。
注意,这张图有误导的地方。除驱动器以外,其它 broker 也能与 Zookeeper 通信。因此,每个 broker 都应该画一条连接 ZK 的线。无论如何,画太多线将导致该图难以阅读。该图还忽视了,在不需要驱动器介入的情况下,能够修改 Zookeeper 中的状况的外部命令行工具和工具包。正如上面讨论的那样,那些难题导致了驱动器缓存中状况难以真正的反映 Zookeeper 中的持久化状况。
在 Proposed 架构中,三个驱动器节点取代了 Zookeeper 的 3 个节点。驱动器节点和 broker 节点在不同的 JVM 中运行。驱动器节点为元数据南区选举一个 leader 节点,用橙色标识。相较于驱动器向各个 broker 推送元数据更新,在 Proposed 中,各个 broker 从 leader 中拉取元数据更新。这就是箭头指向驱动器的原因。
注意,驱动器进程与 broker 进程是逻辑隔离的,它们不必做物理隔离。在某些情况下,将部分或者全部驱动器进程与 broker 进程布署在一个节点上,有其存在的意义。这和 Zookeeper 进程和 Kafka broker 布署在同一个节点上(目前小型软件产业的布署方式)类似。通常,各种各样的布署方式都可能出现,包括在同一个 JVM 中运行。
驱动器 Quorum
驱动器节点由管理工作元数据日志的 Raft quorum(Raft 议会选举机制)组成。该日志包括每次更改软件产业的元数据有关信息。目前,一切信息都储存在 Zookeeper 中,比如 topic、partition、ISR、实用性等,在捷伊架构中,这些信息都将存在日志中。
通过 Raft 算法,驱动器节点将在它们间议会选举 leader,不需要倚赖任何外部系统。元数据日志的 leader 被称作活动的(active)驱动器。活动驱动器处理所有来自 broker 的 RPC 调用。follower 驱动器(相对 leader 控制来说)从活动驱动器中复制所有写入的数据,并且当活动驱动器故障时,作为热备(hot standbys)。由于驱动器HMPP跟踪最新状况,驱动器故障切换将不再需要花很多时间转移最新状况到捷伊驱动器上。
和 Zookeeper 一样,Raft 需要大多数节点能正常运行,才能正常工作。因此,3 个节点驱动器软件产业允许一个节点失效。5 个节点的驱动器软件产业允许两个节点失效,以此类推。
驱动器将按周期将元数据快照写入磁盘。尽管在概念上和压缩相似,但代码路径有些许不同,原因是他们从缓存中加载状况,而不是从磁盘中钟炳昌日志。
管理工作 broker 元数据
不同于驱动器将更新推送至各个 broker,那些 broker 将通过捷伊 MetadataFetch API 从活动驱动器拉取更新。
MetadataFetch 与拉取请求类似。就和拉取请求一样,broker 将记录最近一次拉取的更捷伊 offset,并且只从活动驱动器请求捷伊更新。
broker 将拉取到的元数据持久化至磁盘。这将使得 broker 启动的非常快,即使有成百上千南区,甚至上百万个南区。(注意,此种持久化是一种优化,如果忽视此种优化能提高开发效率,那么他们能在第一个版本中忽视它)
大多数时候,broker 只需要拉取增量状况(deltas),而不是HMPP状况。无论如何,如果 broker 的状况与活动驱动器的状况差距过大,或者 broker 完全没有缓存元数据,驱动器将返回HMPP元数据镜像,而不是返回一些列的增量数据。
broker 按周期从活动驱动器中请求元数据更新。该请求与此同时作为心跳发送,驱动器以此获知该 broker 是存活状况。
注意,尽管本节只讨论管理工作 broker 的元数据,但管理工作客户端的元数据对于可伸缩性也很重要。一旦发送增量元数据更捷伊基础设施搭建好后,那些基础设施将用于客户端和 broker。毕竟,一般情形下,客户端的数量会大于 broker 的数量。随着南区数量的增长,客户端感兴趣的南区也会越多,所以,以增量的方式将元数据更新交付给客户端将变得越来越重要。他们将在接下来的几个小节中讨论这个难题。
broker 状况机
目前,broker 在启动以后,马上在 Zookeeper 中注册自己。注册的过程完成两件事:告诉 broker 它是否被议会选举为驱动器,让其它节点知道如何和它联系。
在后 Zookeeper 时代的世界里,broker 通过驱动器 quorum 注册自己,而不是 Zookeeper。
当前,一个能够联系 Zookeeper ,但由驱动器南区的 broker,能继续为使用者的请求提供服务,但不会接收任何元数据更新。这将导致一些令人困惑、难以应对的情况。例如,一个 producer 通过 acks=1 继续发送数据给 leader,但实际上该 leader 已经不再是真正的 leader,但这个失效的 leader 难以接收驱动器的 LeaderAndIsrRequest,从而去除 leader 地位。
在后 ZK 时代的世界里,软件产业的成员关系集成在元数据更新中。如果 broker 难以接收元数据更新,将从软件产业的成员中去除。尽管该 broker 仍然可能被某一特殊的客户端南区,但如果该 broker 是由驱动器南区的,仍将从软件产业中去除。
broker 状况
Offline
当 broker 进程为 Offline 状况,它要么没有启动,要么在执行启动所需的单节点任务,比如,初始化 JVM 或者执行恢复日志。
Fenced
当 broker 处于 Fenced 状况,它将不再响应来自客户端的 RPC 请求。broker 在启动后,尝试拉取最捷伊元数据时,将处于 fenced 状况。如果难以联系活动驱动器,broker 将重新进入 fenced 状况。发给客户端的元数据应该忽视状况为 fenced 的 broker。
Online
当 broker 状况为 online 时,表示该 broker 准备好响应客户端的请求了。
Stopping
broker 进入 stoppoing 状况表示它们接到 SIGINT 信号。该信号表明系统管理工作员要关闭 broker。
broker 在 stopping 状况时,仍在运行,但他们尝试将南区 leader 从 broker 中去除。
最后,活动驱动器在 MetadataFetchResponse 中添加一串特殊的代码,要求 broker 进入 offline 状况。或者,如果 leader 在预先定义的时间内没有动作,broker 将关闭。
将已有的 API 迁移到驱动器中
之前的很多直接写入 Zookeeper 的操作将变为写入驱动器。例如,更改实用性、修改留存默认授权的 ACLs,等等。
新版本的客户端应该将那些操作直接发给活动驱动器。这是一个向后兼容的更改:在新旧软件产业中都能正常工作。为了兼容老客户端,那些操作将随机发送给 broker,broker 将那些请求转发给活动驱动器。
捷伊控制器 API
在某些情况下,他们需要创建一个捷伊 API 替换之前通过 Zookeeper 完成的操作。例如,当南区 leader 要修改 in-sync replica 集合时,在后 ZK 时代的世界里,它直接修改 Zookeeper,现在,leader 发起一个 RPC 请求到活动驱动器。
从工具包中去除直接访问 Zookeeper
目前,一些工具和脚本直接联系 Zookeeper。在后 Zookeeper 时代的世界里,那些工具将被 Kafka API 取代。幸运的是,“KIP-4:命令行和中心化管理工作操作”,在几年前开始去除直接访问 Zookeeper,并且快完成了。