简单理解kafka原理

kafka初探

Posted by 果果 on July 9, 2022

Kafka 是由Linkedin公司开发的,它是一个分布式的,支持多分区、多副本,基于Zookeeper的分布式消息流平台,它同时也是一款开源的基于发布订阅模式的消息引擎系统。

1 基本概念

  • 消息:Kafka中的数据单元被称为消息,也被称为记录,可以把它看作数据库表中某一行的记录。
  • 批次:为了提高效率, 消息会分批次写入Kafka,批次就代指的是一组消息。
  • 主题:消息的种类称为 主题(Topic),可以说一个主题代表了一类消息,相当于是对消息进行分类。主题就像是数据库中的表。
  • 分区:主题可以被分为若干个分区(partition),同一个主题中的分区可以不在一个机器上,有可能会部署在多个机器上,由此来实现 kafka 的伸缩性,单一主题中的分区有序,但是无法保证主题中所有的分区有序。

k1

  • 生产者:向主题发布消息的客户端应用程序称为生产者(Producer),生产者用于持续不断的向某个主题发送消息。
  • 消费者:订阅主题消息的客户端程序称为消费者(Consumer),消费者用于处理生产者产生的消息。
  • 消费者群组:生产者与消费者的关系就如同餐厅中的厨师和顾客之间的关系一样,一个厨师对应多个顾客,也就是一个生产者对应多个消费者,消费者群组(Consumer Group)指的就是由一个或多个消费者组成的群体。

k2

  • 偏移量:偏移量(Consumer Offset)是一种元数据,它是一个不断递增的整数值,用来记录消费者发生重平衡时的位置,以便用来恢复数据。
  • broker: 一个独立的 Kafka 服务器就被称为 broker,broker 接收来自生产者的消息,为消息设置偏移量,并提交消息到磁盘保存。
  • broker 集群:broker 是集群 的组成部分,broker 集群由一个或多个 broker 组成,每个集群都有一个 broker 同时充当了集群控制器的角色(自动从集群的活跃成员中选举出来)。
  • 副本:Kafka中消息的备份又叫做 副本(Replica),副本的数量是可以配置的,Kafka 定义了两类副本:领导者副本(Leader Replica) 和 追随者副本(Follower Replica),前者对外提供服务,后者只是被动跟随。
  • 重平衡:Rebalance。消费者组内某个消费者实例挂掉后,其他消费者实例自动重新分配订阅主题分区的过程。Rebalance是 Kafka 消费者端实现高可用的重要手段。

2.1 系统架构

一个典型的Kafka集群中包含若干Producer(可以是web前端产生的Page View,或者是服务器日志,系统CPU、Memory等),若干broker(Kafka支持水平扩展,一般broker数量越多,集群吞吐率越高),若干Consumer Group,以及一个Zookeeper集群。Kafka通过Zookeeper管理集群配置,选举leader,以及在Consumer Group发生变化时进行rebalance。Producer使用push模式将消息发布到broker,Consumer使用pull模式从broker订阅并消费消息。

k3

2.2 生产者

2.2.1 数据执行流程

在 Kafka 中,我们把产生消息的那一方称为生产者,比如我们经常回去淘宝购物,你打开淘宝的那一刻,你的登陆信息,登陆次数都会作为消息传输到 Kafka 后台,当你浏览购物的时候,你的浏览信息,你的搜索指数,你的购物爱好都会作为一个个消息传递给 Kafka 后台,然后淘宝会根据你的爱好做智能推荐,致使你的钱包从来都禁不住诱惑,那么这些生产者产生的消息是怎么传到 Kafka 应用程序的呢?发送过程是怎么样的呢?

尽管消息的产生非常简单,但是消息的发送过程还是比较复杂的,如图:

k4

总结一下流程:创建对象(主题、分区、key/value)-> 序列化数据 -> 到达分区(可自己指定,也可以通过key hash)-> 放入批次(相同主题和分区) -> 独立线程发送 -> 返回主题/分区/分区偏移量/时间戳。

2.2.2 分区策略

Kafka 对于数据的读写是以分区为粒度的,分区可以分布在多个主机(Broker)中,这样每个节点能够实现独立的数据写入和读取,并且能够通过增加新的节点来增加 Kafka 集群的吞吐量,通过分区部署在多个 Broker 来实现负载均衡的效果,下面我们看看数据如何选择分区。

  • 方式1:顺序轮询(默认)
  • 方式2:随机轮询 它要逊于轮询策略,数据会分布不均匀,
  • 方式3:key hash

这个策略也叫做 key-ordering 策略,Kafka 中每条消息都会有自己的key,一旦消息被定义了 Key,那么你就可以保证同一个 Key 的所有消息都进入到相同的分区里面,由于每个分区下的消息处理都是有顺序的,故这个策略被称为按消息键保序策略。

2.3 消费者

2.3.1 消费者群组

  • Kafka 消费者从属于消费者群组。
  • 一个群组中的消费者订阅的都是相同的主题,每个消费者接收主题一部分分区的消息。
  • 一个组群内,一个分区只能被一个消费者消费
  • 一个分区可以被不同组群内不同消费者消费
  • 向群组中增加消费者是横向伸缩消费能力的主要方式
  • 只需写入一次消息,可以支持任意多的应用读取这个消息

k5

如果应用需要读取全量消息,那么请为该应用设置一个消费组;如果该应用消费能力不足,那么可以考虑在这个消费组里增加消费者。

2.3.2 消费者重平衡

我们从上面的消费者演变图中可以知道这么一个过程:把分区的所有权通过一个消费者转到其他消费者的行为称为重平衡,英文名也叫做 Rebalance 。

重平衡非常重要,它为消费者群组带来了高可用性 和 伸缩性

消费者通过向组织协调者(Kafka Broker)发送心跳来维护自己是消费者组的一员并确认其拥有的分区。

当消费者检索记录或者提交它所消费的记录时就会发送心跳。如果过了一段时间 Kafka 停止发送心跳了,会话(Session)就会过期,组织协调者就会认为这个 Consumer 已经死亡,就会触发一次重平衡。

重平衡是一把双刃剑,它为消费者群组带来高可用性和伸缩性的同时,还有有一些明显的缺点(bug),每次重平衡过程中都会导致万物静止,参考 JVM 中的垃圾回收机制,也就是 Stop The World ,STW。在重平衡期间,消费者组中的消费者实例都会停止消费,等待重平衡的完成,而且重平衡这个过程很慢……

3 特性分析

这里才是内容的重点,不仅需要知道Kafka的特性,还需要知道支持这些特性的原因:

  • 消息路由(不支持):Kafka在处理消息之前是不允许消费者过滤一个主题中的消息。一个订阅的消费者在没有异常情况下会接受一个分区中的所有消息。
  • 消息有序(支持):当消费消息时,如果消费失败,消息不会被放回,所以整个消费过程都是有序进行;
  • 消息时序(不支持):消息直接发送,不会延迟发送,或者指定消息的TTL。
  • 容错处理(集群支持/消息不支持):集群容错能力高,因为是分布式部署,但是消息容错处理弱,因为消息消费失败,需要程序员手动处理,Kafka不支持消息重新进行消费。
  • 伸缩(非常好):通过扩充分区和消费者数量,实现分区扩容,并提升消费速度。
  • 持久化(非常好):数据存储在磁盘,可以随时订阅消费,消费完后,数据仍然保留。
  • 消息回溯(支持):因为消息支持持久化,就支持回溯,可以理解是附带的功能。
  • 高吞吐(非常好):因为Kafka内部同一个主题包含多个分区,所以实现分布式存储,然后消费者数量可以扩充到和分区数量一致,保证了Kafka的高吞吐。