kafka机制梳理

前言

最近我们小组在尝试搭建大数据系统,各种没听过的名词搞得我们很头大,于是准备好好弄清楚kafka到底是个什么东西~

简介

简单来讲,kafka维护了一个消息队列,以发布-订阅的模式维护了消息发布者和接收者之间的通讯。下面看下它的主要结构吧~

整体物理结构

  • 三个关键的角色就是:生产者、消费者、服务器(实在不知道Broker可以咋翻译,暂且理解成服务器吧)
  • 宏观来看整体流程就是:
    • 生产者往服务器中写消息
    • 消费者从服务器中拿消息

具体如何写如何读,服务器如何组织消息的存储,往下看

Producer

生产者发布消息,如上图所示,producer必须要指定消息的topic,topic可以理解成消息的类别,因为这个是消费者的订阅单位。partition和key是可选的这里不赘述了

Broker

一个broker可以理解成一个服务器节点,物理上用来存放消息队列。

Topic

因为每条消息都属于某个topic,所以逻辑上消息是按topic存储的。而由于一个topic可能非常大,所以会分成很多个partition,那么为了负载均衡,通常一个topic的不同partition会分配到不同的borker上。具体哪个topic的哪个partition分配在哪个broker上要看开发者采用的策略。但这个是物理上的事情啦~我们等下从逻辑上分析它们和consumer之间的对应关系

Partition

一个partition是一个队列,每个元素(消息)有一个自己的标号,称为offset。根据offset可以O(1)的查找消息。(仿佛是队列和数组的结合体~)
新的消息来了之后会被添加到队尾,因此partition是按照到达时间排序的有序队列

Consumer & Consumer Group

消费者从broker获取它订阅的topic的消息。
一个Consumer Group里可以有多个Consumer,其实Consumer Group和Consumer之间的关系就像一个team和组员之间的关系一样。一个team要一起完成工作A(分为part1、2)、B(分为part1、2),但是活太多了要分一下任务呀,于是组员a负责工作A的part1,组员b负责工作B的part1,组员c负责工作A、B的part2(如果两个part2比较轻松的话~)。

类似的,上面例子里的team就是Consumer Group,订阅消息是以group为单位的,于是上面的工作A和B就好比是Consumer Group订阅的两个topic,而两个topic分别都有两个partition。于是一共有4个partition分给3个consumer(对应例子中的组员)。

这样一来关系就很明确了:

  • 一个Consumer Group里的consumer们订阅的topic是一样的
  • 一个consumer可以负责多个partition
  • 一个partition不能对应多个consumer(同一个consumer group内)
    • 这点细说一下,因为有可能有多个consumer group订阅了同一个topic,每个consumer group的处理速度可能不一样,所以每个consumer要自己保存一个状态记录自己负责的partition读到哪了。如果在同一个consumer group内有多个consumer负责同一个partition,那么他们就要共同读写这个状态,这样维护这个状态就比较复杂(比如需要使用锁之类的)。

各部分逻辑关系

由于第一张图把kafka集群当成一个黑盒,所以没有画出broker、topic、partition与producer、consumer之间的关系。为了更清楚的理解,下面的例子将他们之间的关系画出来了~

下例假设kafka集群中有2个broker,1个topic,这个topic有4个partition;两个consumer group,分别有2个和4个consumer,这两个consumer group都只订阅了Topic0。

可以看到consumer groupA中,consumer的数量少于这个group订阅了的partition的数量,因此会有一个consumer对应多个partition的情况。
而consumer groupB中,二者数量刚好相等,因此每个consumer对应一个partition。
假如有一个consumer group的consumer数量少于其订阅的partition,那么就会有consumer闲着(前面说过不能多个consumer对应一个partition),这样的设计不好,很浪费。

Partition副本

前面的关系梳理为了简单,忽略了副本的存在。实际上kafka为了保证数据的可靠性,会给每个partition创建多个副本存储在不同的broker上,这样一来如果某个broker突然挂掉,其他broker上与之对应的partition也能继续work~

下面举个例子,为了简单,例中仅有一个topic,它有2个partition,每个partition有3个副本。阴影的partition是leader,其余的都是follower

  • 每个partition会有一个leader,其余的都是它的follower。
  • 每次producer和consumer对于partition的读写都会被kafka指引到leader上(具体是如何找到leader的我就没有研究啦)
  • 如果有broker挂了,比如上图中的Broker0,那么p0的leader就挂了,kafka会在p0剩下的两个follower中选一个(选举规则我也没研究)重新作为leader
  • 在没有broker挂掉的平时,follower跟leader的关系有点类似consumer和partition的关系,从leader pull数据使得自己的数据与leader保持一致

总结

关于kafka我完全是一个初学者,因此文中哪里理解的不对、描述有问题的地方欢迎评论or邮件指出!一起进步呀~~


参考链接
kafka官方介绍
Kafka官方文档
Kafka官方中文文档
Kafka中partition和消费者的对应关系
Thorough Introduction To Apache Kafka
StackOverflow - Understanding Kafka Topics and Partitions

觉得有帮助到你的话,欢迎打赏~~