关于Kafka你需要知道的一切
初学者的简单指南
Kafka,这个单纯从LinkedIn开始的技术,现在已经成为大多数科技公司不可缺少的工具包。
每一项技术的诞生都是为了处理一个问题。Kafka也不例外。
说到这里,让我们回到原点,告诉你关于这项神奇技术的一切。
让我们开始吧!
为什么我们需要Kafka?
订单发生时通知其他服务
在我们深入研究之前,有必要重温一下Kafka最初被发明的原因。
想象一下,为一家电子商务公司维护一组微服务。
当有订单发生时,Order 服务器会通知其他服务,具体如下。
- 钱包服务器从用户的账户中扣除金额
- 仓库服务器扣除该物品的库存数量
- 物流服务器将物品运送出去
当订单发生时要通知更多的服务,其复杂性就会升级。
订单服务器需要做以下工作。
- 跟踪要通知的对象
- 确保所有收件人确实已经收到并处理了该信息
- 管理连接和收件人的路由策略。
正如你所知道的,这是不可能扩展的。
因此,Kafka的出现。
消息队列与Pub-Sub
订单服务器只需将消息发布到Pub-Sub/消息队列上
消息队列和Pub-Sub系统都是解决上述问题的关键。
与其让Order服务器维护事件通知,Order 服务器将事件发布给一个中间人,这个中间人的行为像一个队列。
对该队列感兴趣的服务器,通常被称为消费者,订阅该队列并相应地消费事件。
消息队列和Pub-Sub系统之间的区别在于一个微妙的方式。
消息队列
消息队列是一个类似于队列的结构,一个消息被发布并被消费一次,而且只有一次。
这对于那些非空闲的进程来说很方便,而且事件应该只由一个消费者处理。
RabbitMQ 最初被设计为一个消息队列。
Pub-Sub 系统
另一方面,一个 Pub-Sub 系统允许一个消息被多个消费者多次消费。
我们之前的电子商务例子采用了一个Pub-Sub解决方案。订单事件被许多消费者消费。
Kafka被设计成既是一个消息队列又是一个Pub-Sub系统。我们将在后面的章节中深入探讨如何做到这一点。
Kafka组件
为了充分了解Kafka是如何工作的,让我们来剖析一下Kafka的组件,并分别讨论它们。以下是我们要讨论的内容。
- Kafka经纪人和集群
- 发布者
- 消费者
- 主题
- 分区
- 消费者组
- 复制
- 仓库管理员(Zookeeper)
- 长时间轮询
Kafka经纪人和集群

Kafka经纪人和集群
Kafka只不过是一个管理数据发布和消费的服务器。
一个Kafka服务器被称为一个经纪人。
维护同一组主题的经纪商的集合被称为Kafka集群。
发布者
发布者向Kafka经纪人发布信息
一个向Kafka经纪人发布数据的服务器被称为发布者。
我们之前提到的Order 服务器就是一个发布者的例子。
消费者
消费者从Kafka代理处消费
另一方面,消费者是一个从Kafka主题订阅和消费数据的服务器。
在我们之前的例子中,Wallet 服务器、Warehouse 服务器和Logistic 服务器充当了Order 主题的消费者。
主题
Kafka代理中的不同主题
一个Kafka代理维护着不同类型的事件,比如说以下这些。
- 订单创建事件
- 订单取消事件
- 断货事件
这些事件中的每一个都是大量的数据流。一个主题只是一种类型的事件或数据流。
当发布到Kafka时,发布者会指定消息应该在哪个主题中发布。
一个话题是一个只需追加的日志。将消息追加到一个主题中,就像将数据追加到一个队列中一样,需要O(1)的恒定时间,因此,它非常快。
分区
主题被分散到各个分区中
一个主题是一个只附加的日志,存储在Kafka代理上。
随着消息数量的增加,经纪人在一个特定的主题上能存储的数据是有限的。
与其把所有的数据都存储在一个仅有附录的日志中,一个主题可以被分割成多个分区。每个分区存储一个特定主题的部分数据。
这就类似于数据库分片。
主题是根据分区来分片的。同一主题的一个分区可以存储在同一个或不同的Kafka代理上。这使得Kafka具有高度的可扩展性。
发布者在发布前会指定消息的主题和分区。因此,发布者有责任确保分区的逻辑不会导致热分区的出现。
偏移量
分区中的偏移量
偏移量是一个分区中消息的唯一索引。
当Kafka将数据推送给消费者时,它会增加并跟踪当前的偏移量。
有两种类型的偏移量是值得强调的。
- 当前偏移量
- 已承诺的偏移量
一个data ,可以通过指定主题、分区和消息的偏移量来具体检索。
说到偏移量,有很多细节。我们将在另一篇文章中进一步谈论它们。
消费者组
如前所述,Kafka既是一个消息队列也是一个Pub-Sub系统。这一点通过消费者组设计得很优雅。
消费者可以消费多个分区,但每个分区只能被同一个组的一个消费者消费。
一个消费者组由一组消费同一主题的消费者组成。
一个消费者可以同时消费多个分区。然而,每个分区只能由同一组的一个且仅一个消费者消费。
一个分区可以被来自不同消费者群体的多个消费者消费
消费者群体是相互独立的。不同的组可以用不同的偏移量从同一主题中同时消费。
一个队列是通过将所有的消费者放在同一个组中实现的。同一分区的消息不会被来自类似组的不同消费者同时消费。
队列是在分区层面上实现的。因此,如果要按顺序处理数据流,发布者必须确保数据总是被推送到同一个分区。
另一方面,一个Pub-Sub系统是通过多个消费者组实现的。消费者组之间互不相识,使用单独的偏移量来消费数据。
在前面的例子中,Wallet 服务器和Logistic 服务器各属于一个不同的消费者组,并分别消费数据。
重新平衡和分区分配
当有新的消费者加入时,Kafka会重新平衡
如果一个组中只有一个消费者,那么这个消费者将负责所有可用分区的消费。
当一个新的消费者加入到组中时,例如,增加了一个新的服务器实例,Kafka将执行再平衡,并将一部分分区分配给新的消费者。
这确保了每个消费者分享相同的工作量,因此,允许Kafka具有可扩展性。
Kafka使用自己的再平衡策略来进行分区重新分配,这值得另一篇文章来讨论。
复制品
复制是在分区层面上创建的,可以存储在相同/不同的broker中。
单点故障是每个分布式系统的恶梦。Kafka也不例外。
如果一个经纪商发生故障,存储在经纪商上的分区可能就无法使用。
因此,副本是在分区层面上创建的。
复制是为每个分区创建的,并存储在不同的Kafka经纪商上。每个分区都会选出一个领导者,为发布者和消费者服务。
复制体不断地从领导者那里同步数据。当领头羊倒下时,Zookeeper会加入进来,帮助领头羊的选举。
守望者(Zookeeper
正如你可能在思考的那样,我们的拼图中还缺少一些碎片。
- 我们如何知道每个分区的领导人?
- 如何知道每个主题的分区数量?
- 我们如何知道每个消费者群体的最新偏移量?
- 我们如何知道每个消费者组中的消费者数量?
这就是zookeeper开始发挥作用的地方。它是一个服务同步系统,存储元数据并协调Kafka中的分布式系统。
它主要参与以下方面的工作。
- 领导者选举 - 确保每个分区都有一个领导者
- 集群成员 - 追踪集群中所有的功能经纪商
- 主题配置 - 追踪所有可用的主题、分区和它们的副本
- 访问控制列表 - 追踪每个组中消费者的数量和他们的访问权
- 配额 - 追踪每个客户可以读和写的数据量
长时间轮询
这里有一个百万美元的问题,Kafka是如何向其消费者推送消息的?
RabbitMQ采用了推送模式。代理商与消费者保持一个持久的TCP连接,如果有可用的数据,就把数据推送给他们。
然而,推送模式有可能会使消费者不堪重负。如果经纪人推送数据的速度比消费者处理数据的速度快,消费者可能会落伍。RabbitMQ 对此确实有一个解决方案,但这超出了我们的范围。
长轮询等待模式方法
Kafka利用了一个拉动模式,又称长轮询,而不是。消费者周期性地从代理处拉取数据。因此,消费者只有在准备好的时候才能拉动数据。然而,如果分区上没有数据,消费者的定期轮询可能会导致资源浪费。
Kafka通过使用 "长轮询 "的等待模式方法解决了这个问题。简而言之,如果分区上没有数据,Kafka不会返回一个空响应。相反,代理持有连接并等待数据的到来,然后再返回给消费者。
这就减轻了消费者在分区没有数据时的频繁轮询,防止了资源的浪费。