Fuhui

Kafka中消息分配策略


非淡泊无以明,非宁静无以致远

Question

关于kafkapartationconsumer的是如何执行分配的。今早骑自行车的时候突然想起这个问题。它是怎么分配的,我记得我看到好几次相关的介绍文章,现在却想不起来?

sense

很多时候,我们在看完一篇技术文档时,感觉对其中的内容都了解了,其实不然。这也是所谓的被动输入和主动输出的区别所在。相比主动输出而言,被动输入缺少了深层思考的态度。得到一些老师的课里就谈到过主动输出的重要性。

很多概念都已经记不起来了,文章的内容可能也不够准确,但重在思考和想法的过程:

Thinking

partaion是数据的存储单位,一个topic至少存在一个partationconsumer使用主动拉数据的方式来消费消息,这就是所有已知概念。那么partationconsumer是如何分配的呢?这里我们假设消息数据总量是一样的。

首先,应该存在一个类似LVS的负载均衡器,因为当consumer增加或者减少时,对应的分配策略也需要做相应的调整。在consumer注册成为消费者时,提交的信息中有consumer Group的概念,这非常好理解,即同一个组的consumer会独立处理一份数据。同时,因为有了Group,我们在管理的时候就会简单很多。当然,所有的讨论都是以一个Group为前提的。

1:1

从最简单的开始考虑,假设现在partationconsumer的数量比例是1:1,那就没有那么多事了,简单明了。

1:2

假设是1:2呢?问题来了,好比现在只有一个数据,但有AB两个线程都要读它,且AB中有且只有一个能读到。这种情况在计算机中相当普遍,通用的处理方式就是加锁,以保证数据只被其中一个线程处理。但加锁就意味着性能开销,尤其是高并发的场景。

继续按照这个思路来考虑,两个consumer同时向一个partation发起请求,需要一个全局锁来控制每个消息只能返回给请求中的一个。相比较1:1的方式,这样的性能肯定是提高了不少。

2:1

假设是2:1呢?这个也很直观,两份数据,但只有一个消费者,那肯定都需要这一个消费者来处理了,就跟CPU任务调度还有些类似。

如果跟1:2的分配策略比较呢?这里通过将原来的一份数据平均分成两份,去掉了1:2中加锁的开销,但只有一个connsumer来消费数据。好比是单核CPU任意处理数据跟双核CPU加锁处理数据。

2:2

假设是2:2呢,我们可以平均分配partationconsumer,而且这样系统性能却得到最大提升,不仅去掉了锁的开销,还有两个线程来同时消费。

结论

通过上面的对比,我们可以清楚的发现,通过调整partationconsumer的数量就可以将系统性能达到最大,完全不需要引入锁机制。这样想的话,分配就很简单了。