Kafka Controller Redesign 方案

转载自  Kafka Controller Redesign 方案

Kafka Controller 是 Kafka 的核心组件,在前面的文章中,已经详细讲述过 Controller 部分的内容。在过去的几年根据大家在生产环境中应用的反馈,Controller 也积累了一些比较大的问题,而针对这些问题的修复,代码的改动量都是非常大的,无疑是一次重构,因此,社区准备在新版的系统里对 Controller 做一些相应的优化(0.11.0及以后的版本),相应的设计方案见:Kafka Controller Redesign,本文的内容就是结合这篇文章做一个简单的总结。

https://docs.google.com/document/d/1rLDmzDOGQQeSiMANP0rC2RYp_L7nUGHzFD9MQISgXYM/edit#heading=h.pxfjarumuhko

 

Controller 功能

在一个 Kafka 中,Controller 要处理的事情总结如下表所示:

 

 

Controller 目前存在的问题

之所以要重新设计 Controller,是因为现在的 Controller 积累了一些比较难解决的问题,这些问题解决起来,代码改动量都是巨大的,甚至需要改变 controller 部门的设计,基本就跟重构差不多了,下面我们先来了看一下 controller 之前(主要是 0.11.0 之前的版本)存在的一些问题。

目前遇到的比较大的问题有以下几个:

  1. Partition 级别同步 zk 写;

  2. sequential per-partition controller-to-broker requests;

  3. Controller 复杂的并发语义;

  4. 代码组织混乱;

  5. 控制类请求与数据类请求未分离;

  6. Controller 给 broker 的请求中没有 broker 的 generation信息;

  7. ZkClient 阻碍 Client 的状态管理。

 

Partition 级别同步 zk 写

zookeeper 的同步写意味着在下次写之前需要等待前面整个过程的结束,而且由于它们都是 partition 粒度的(一个 Partition 一个 Partition 的去执行写操作),对于 Partition 非常多的集群来说,需要等待的时间会更长,Controller 通常会在下面这两个地方做 Partition 级别 zookeeper 同步写操作:

  1. PartitionStateMachine 在进行触发 leader 选举(partition 目的状态是 OnlinePartition),将会触发上面的操作;

  2. ReplicaStateMachine 更新 LeaderAndIsr 信息到 zk(replica 状态转变为 OfflineReplica),这种情况也触发这种情况,它既阻碍了 Controller 进程,也有可能会 zk 造成压力。

 

sequential per-partition controller-to-broker requests

Controller 在向 Broker 发送请求,有些情况下也是 Partition 粒度去发送的,效率非常低,比如在 Controller 处理 broker shutdown 请求时,这里是按 Partition 级别处理,每处理一个 Partition 都会执行 Partition、Replica 状态变化以及 Metadata 更新,并且调用 sendRequestsToBrokers() 向 broker 发送请求,这样的话,效率将变得非常低。

 

Controller 复杂的并发语义

Controller 需要在多个线程之间共享状态信息,这些线程有:

  1. IO threads handling controlled shutdown requests

  2. The ZkClient org.I0Itec.zkclient.ZkEventThread processing zookeeper callbacks sequentially;

  3. The TopicDeletionManager kafka.controller.DeleteTopicsThread;

  4. Per-broker RequestSendThread within ControllerChannelManager.

所有这些线程都需要访问或修改状态信息(ControllerContext),现在它们是通过 ControllerContext 的 controllerLock(排它锁)实现的,Controller 的并发变得虚弱无力。

 

代码组织混乱

KafkaController 部分的代码组织(KafkaController、PartitionStateMachine 和 ReplicaStateMachine)不是很清晰,比如,下面的问题就很难回答:

  1. where and when does zookeeper get updated?

  2. where and when does a controller-to-broker request get formed?

  3. what impact does a failing zookeeper update or controller-to-broker request have on the cluster state?

这也导致了这部分很多开发者不敢轻易去改动。

 

控制类请求与数据类请求未分离

现在 broker 收到的请求,有来自 client、broker 和 controller 的请求,这些请求都会被放到同一个 requestQueue 中,它们有着同样的优先级,所以来自 client 的请求很可能会影响来自 controller 请求的处理(如果是 leader 变动的请求,ack 设置的不是 all,这种情况有可能会导致数据丢失)。

Controller 给 broker 的请求中没有 broker 的 generation信息

这里的 Broker generation 代表着一个标识,每当它重新加入集群时,这个标识都会变化。如果 Controller 的请求没有这个信息的话,可能会导致一个重启的 Broker 收到之前的请求,让 Broker 进入到一个错误的状态。

比如,Broker 收到之前的 StopReplica 请求,可能会导致副本同步线程退出。

 

ZkClient 阻碍 Client 的状态管理

这里的状态管理指的是当 Client 发生重连或会话过期时,Client 可以监控这种状态变化,并做出一些处理,因为开源版的 ZKClient 在处理 notification 时,是线性处理的,一些 notification 会被先放到 ZkEventThread’s queue 中,这样会导致一些最新的 notification 不能及时被处理,特别是与 zk 连接断开重连的情况。

 

Controller 改进方案

关于上述问题,Kafka 提出了一些改进方案,有些已经在最新版的系统中实现,有的还在规划中。

 

使用异步的 zk API

Zookeeper 的 client 提供三种执行请求的方式:

  1. 同步调用,意味着下次请求需要等待当前当前请求的完成;

  2. 异步调用,意味着不需要等待当前请求的完成就可以开始下次请求的执行,并且我们可以通过回调机制去处理请求返回的结果;

  3. 单请求的 batch 调用,意味着 batch 内的所有请求都会在一次事务处理中完成,这里需要关注的是 zookeeper 的 server 对单请求的大小是有限制的(jute.maxbuffer)。

文章中给出了三种请求的测试结果,Kafka 最后选取的是异步处理机制,因为对于单请求处理,异步处理更加简洁,并且相比于同步处理还可以保持一个更好的写性能。

improve controller-to-broker request batching

这个在设计文档还是 TODO 状态,具体的方案还没确定,不过基本可以猜测一下,因为目的是提高 batch 发送能力,那么只能是在调用对每个 broker 的 RequestSenderThread 线程发送请求之前,做一下检测,而不是来一个请求立马就发送,这是一个性能与时间的权衡,如果不是立马发送请求,那么可能会带来 broker 短时 metadata 信息的不一致,这个不一致时间不同的应用场景要求是不一样的。

 

单线程的事件处理模型

采用单线程的时间处理模型将极大简化 Controller 的并发实现,只允许这个线程访问和修改 Controller 的本地状态信息,因此在 Controller 部分也就不需要到处加锁来保证线程安全了。

目前 1.1.0 的实现中,Controller 使用了一个 ControllerEventThread 线程来处理所有的 event,目前可以支持13种不同类型事件:

  1. Idle:代表当前 ControllerEventThread 处理空闲状态;

  2. ControllerChange:Controller 切换处理;

  3. BrokerChange:Broker 变动处理,broker 可能有上线或掉线;

  4. TopicChange:Topic 新增处理;

  5. TopicDeletion:Topic 删除处理;

  6. PartitionReassignment:Partition 副本迁移处理;

  7. AutoLeaderBalance:自动 rebalance 处理;

  8. ManualLeaderBalance:最优 leader 选举处理,这里叫做手动 rebalance,手动去切流量;

  9. ControlledShutdown:优雅关闭 broker;

  10. IsrChange:Isr 变动处理;

  11. LeaderAndIsrResponseReceived;

  12. LogDirChange:Broker 某个目录失败后的处理(比如磁盘坏掉等);

  13. ControllerShutdown:ControllerEventThread 处理这个事件时,会关闭当前线程。

重构集群状态管理

这部分的改动,目前社区也没有一个很好的解决思路,重构这部分的目的是希望 Partition、Replica 的状态管理变得更清晰一些,让我们从代码中可以清楚地明白状态是在什么时间、什么地方、什么条件下被触发的。这个优化其实是跟上面那个有很大关联,采用单线程的事件处理模型,可以让状态管理也变得更清晰。

prioritize controller requests

我们想要把控制类请求与数据类请求分开,提高 controller 请求的优先级,这样的话即使 Broker 中请求有堆积,Broker 也会优先处理控制类的请求。

这部分的优化可以在网络层的 RequestChannel 中做,RequestChannel 可以根据请求的 id 信息把请求分为正常的和优先的,如果请求是 UpdateMetadataRequest、LeaderAndIsrRequest 或者 StopReplicaRequest,那么这个请求的优先级应该提高。实现方案有以下两种:

  1. 在请求队列中增加一个优先级队列,优先级高的请求放到 the prioritized request queue 中,优先级低的放到普通请求队列中,但是无论使用一个定时拉取(poll)还是2个定时拉取,都会带来其他的问题,要么是增大普通请求的处理延迟,要么是增大了优先级高请求的延迟;

  2. 直接使用优先级队列代替现在的普通队列,设计上更倾向与这一种。

 

目前这部分在1.1.0中还未实现。

Controller 发送请求中添加 broker 的 generation 信息

generation 信息是用来标识当前 broker 加入集群 epoch 信息,每当 broker 重新加入集群中,该 broker.id 对应的 generation 都应该变化(要求递增),目前有两种实现方案:

  1. 为 broker 分配的一个全局唯一的 id,由 controller 广播给其他 broker;

  2. 直接使用 zookeeper 的 zxid 信息(broker.id 注册时的 zxid)。

 

直接使用原生的 Zookeeper client

Client 端的状态管理意味着当 Client 端发生状态变化(像连接中断或回话超时)时,我们有能力做一些操作。其中,zookeeper client 有效的状态(目前的 client 比下面又多了几种状态,这里先不深入)是:

  • NOT_CONNECTED: the initial state of the client;

  • CONNECTING: the client is establishing a connection to zookeeper;

  • CONNECTED: the client has established a connection and session to zookeeper;

  • CLOSED: the session has closed or expired。

有效的状态转移是:

  • NOT_CONNECTED > CONNECTING

  • CONNECTING > CONNECTED

  • CONNECTING > CLOSED

  • CONNECTED > CONNECTING

  • CONNECTED > CLOSED

最开始的设想是直接使用原生 Client 的异步调用方式,这样的话依然可以通过回调方法监控到状态的变化(像连接中断或回话超时),同样,在每次事件处理时,可以通过检查状态信息来监控到 Client 状态的变化,及时做一些处理。

当一个 Client 接收到连接中断的 notification(Client 状态变成了 CONNECTING 状态),它意味着 Client 不能再从 zookeeper 接收到任何 notification 了。如果断开连接,对于 Controller 而言,无论它现在正在做什么它都应该先暂停,因为可能集群的 Controller 已经切换到其他机器上了,只是它还没接收到通知,它如果还在工作,可能会导致集群状态不一致。当连接断开后,Client 可以重新建立连接(re-establish,状态变为 CONNECTED)或者会话过期(状态变为 CLOSED,会话过期是由 zookeeper Server 来决定的)。如果变成了 CONNECTED 状态,Controller 应该重新开始这些暂停的操作,而如果状态变成了 CLOSED 状态,旧的 Controller 就会知道它不再是 controller,应该丢弃掉这些任务。

 

参考

  • Kafka Controller Redesign;

    https://docs.google.com/document/d/1rLDmzDOGQQeSiMANP0rC2RYp_L7nUGHzFD9MQISgXYM/edit#heading=h.pxfjarumuhko

  • Kafka controller重设计。

    https://www.cnblogs.com/huxi2b/p/6980045.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/323254.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

做个人网站的原因

昨天b站上看视频,浏览评论时,看到一个网址 https://xiaoyou66.com/ 博主写了大概一百篇的文章,我进来的时候真的是被这js特效给惊到了,个人网站也能变得这么二次元嘛,讲实话,光是看这酷炫的页面都比较有欲望…

一文理解Netty模型架构

转载自 一文理解Netty模型架构 本文基于Netty4.1展开介绍相关理论模型,使用场景,基本组件、整体架构,知其然且知其所以然,希望给读者提供学习实践参考。 1 Netty简介 Netty是 一个异步事件驱动的网络应用程序框架,用…

尝试涉猎更多领域

昨天b站上看视频,浏览评论时,看到一个网址 https://xiaoyou66.com/ 博主写了大概一百篇的文章,我进来的时候真的是被这js特效给惊到了,个人网站也能变得这么二次元嘛,讲实话,光是看这酷炫的页面都比较有欲望…

聊聊分布式事务,再说说解决方案

前言 最近很久没有写博客了,一方面是因为公司事情最近比较忙,另外一方面是因为在进行 CAP 的下一阶段的开发工作,不过目前已经告一段落了。 接下来还是开始我们今天的话题,说说分布式事务,或者说是我眼中的分布式事务&…

Redis+Tomcat+Nginx集群实现Session共享,Tomcat Session共享

转载自 RedisTomcatNginx集群实现Session共享,Tomcat Session共享 一、Session共享使用tomcat-cluster-redis-session-manager插件实现 插件地址见: https://github.com/ran-jit/tomcat-cluster-redis-session-manager 该插件支持Tomcat7、Tomcat8、To…

个人博客搭建

先下载node.js 用npm或cnpm安装hexo cnpm install hexo 再创建一个文件夹,在文件夹目录下打开cmd 输入 hexo init 输入 hexo s 这就在本地算是完成了一个博客的创建 新建博客hexo n ‘Hello world’ hexo clean hexo s 就可以再次启动,这样 记得先 cn…

C#使用Xamarin开发可移植移动应用进阶篇(10.综合演练,来一份增删改查CRUD)

说点什么.. 呃 也有半个月没更新了. 本来这篇的Demo早就写完了,文章也构思好了.迟迟没发布..是因为实在太忙.. 项目要上线..各种 你们懂的.. 正赶上自己十一人生大事..结婚..所以..忙的那叫一个脚不沾地啊. 今天的学习内容? 使用我们前面所学的技术,写一个增删改查. 效果如下…

hexo部署在码云出现样式问题

然而本地服务器并没有任何问题 重建一个 重新建一个仓库 还是这种情况,回头再找原因,两次都是这种情况,就是配置错了 借用 https://blog.csdn.net/xiangwanpeng/article/details/53155642 https://blog.csdn.net/qq_29347295/article/deta…

当你输入一个网址的时候,实际会发生什么?

转载自 当你输入一个网址的时候,实际会发生什么? 译文:http://igoro.com/archive/what-really-happens-when-you-navigate-to-a-url/ 作为一个软件开发者,你一定会对网络应用如何工作有一个完整的层次化的认知,同样这里也包括这些应用所…

SIMD via C#

简介 TL;DR 我们为C#(准确地说是.NET Core)引入了一套全新的机制,使得C# 以后可以像C/C 一样直接使用intrinsic functions 来直接操作Intel CPU 的大多数SIMD 指令了(从SSE 到AVX2)。 (注意是以后&#xff…

Ae做一个立体地球

Ae做一个立体地球 拿到一张照片 将它变成标题的地球 在AE里 即可变成一个地球 看上去亮多了,再定个关键帧即可旋转

ASP.NET Core 处理 404 Not Found

问题 在没有修改任何配置的情况下,这是用户使用 Chrome 访问不存在的URL时会看到的内容: 幸运的是,处理错误状态代码非常简单,我们将在下面介绍三种技术。 解决方案 在以前的ASP.NET MVC版本中,主要在 web.config 中处…

搭建一个二次元博客

小叙: 因为前段日子尝试过自己搭建网站,也在b站发了视频,奈何技术太菜,被喷的严重。所以决定重构一下网站,改成一个个人博客。这里非常感谢小游提供的主题,感谢他对这么优秀的主题的推广。 如果你正好也要…

从头编写 asp.net core 2.0 web api 基础框架 (5) EF CRUD

Github源码地址:https://github.com/solenovex/Building-asp.net-core-2-web-api-starter-template-from-scratch 这是第一大部分的最后一小部分。要完成CRUD的操作。 Repository Pattern 我们可以直接在Controller访问DbContext,但是可能会有一些问题: …

做这个网站原因之二

讲讲我最近干了什么事吧以及以后该干啥 其实大部分我学到的东西,都写在博客上了,可以通过博客看到一个人的学习轨迹。除了这些,我也尝试拍些视频去学习一些新的东西。视频剪辑,特效什么的都在尝试。 有个视频我也只是随便尝试尝试…

spring cloud+dotnet core搭建微服务架构:配置中心续(五)

前言 上一章最后讲了,更新配置以后需要重启客户端才能生效,这在实际的场景中是不可取的。由于目前Steeltoe配置的重载只能由客户端发起,没有实现处理程序侦听服务器更改事件,所以还没办法实现彻底实现这一功能。这一章的例子&…

聊聊最近吧

讲讲我最近干了什么事吧以及以后该干啥 其实大部分我学到的东西,都写在博客上了,可以通过博客看到一个人的学习轨迹。除了这些,我也尝试拍些视频去学习一些新的东西。视频剪辑,特效什么的都在尝试。 有个视频我也只是随便尝试尝试…

C# 实现虚拟数字人

随着Ai技术的提升和应用,虚拟数字人被广泛应用到各行各业中。为我们的生活和工作提供了非常多的便利和色彩。 通过设置虚拟数字人的位置大小,可以让数字人可以在电脑屏幕各个位置显示: 虚拟数字人素材: 虚拟数字人(实际有语音&am…

AspectCore.Extension.Reflection : .NET Core反射扩展库

在从零实现AOP的过程中,难免会需要大量反射相关的操作,虽然在.net 4.5/.net core中反射的性能有了大幅的优化,但为了追求极致性能,自己实现了部分反射的替代方案,包括构造器调用、方法调用、字段读写,属性读…

【分享】通过手游赚¥

这本来是个回答,但是在知乎被删了,于是我决定还是在自己网站再发一份,特么知乎店大欺人,我一这么水回答,还被认为是广告营销 首先说明一点,这个完全是自我经历,一种分享吧。觉得假的自然假。 我…