设为首页 加入收藏

TOP

Kafka Controller Redesign方案(二)
2018-10-13 10:08:18 】 浏览:420
Tags:Kafka Controller Redesign 方案
r 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,应该丢弃掉这些任务。

参考

 

首页 上一页 1 2 下一页 尾页 2/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇ssh 服务突然连接不了案例总结 下一篇说说MQ之RocketMQ(三)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目