大白话带你认识Kafka

本文探讨了Kafka作为消息队列的优势,其高性能、生态兼容性和流处理能力。文章介绍了Kafka的起源、关键概念、队列模型与发布-订阅模型的区别,以及如何利用分区、副本和Zookeeper保证消息处理和顺序。
摘要由CSDN通过智能技术生成

前言

我们现在经常提到 Kafka 的时候就已经默认它是一个非常优秀的消息队列了,我们也会经常拿它给 RocketMQ、RabbitMQ 对比。我觉得 Kafka 相比其他消息队列主要的优势如下:

1极致的性能 :基于 Scala 和 Java 语言开发,设计中大量使用了批量处理和异步的思想,最高可以每秒处理千万级别的消息。
2生态系统兼容性无可匹敌 :Kafka 与周边生态系统的兼容性是最好的没有之一,尤其在大数据和流计算领域。

实际上在早期的时候 Kafka 并不是一个合格的消息队列,早期的 Kafka 在消息队列领域就像是一个衣衫褴褛的孩子一样,功能不完备并且有一些小问题比如丢失消息、不保证消息可靠性等等。当然,这也和 LinkedIn 最早开发 Kafka 用于处理海量的日志有很大关系,哈哈哈,人家本来最开始就不是为了作为消息队列滴,谁知道后面误打误撞在消息队列领域占据了一席之地。

随着后续的发展,这些短板都被 Kafka 逐步修复完善。所以,Kafka 作为消息队列不可靠这个说法已经过时!

初识 Kafka

先来看一下官网对其的介绍,应该是最权威和实时的了。是英文也没有关系,我已经将比较重要的信息都为你提取出来了。

从官方介绍中我们可以得到以下信息:Kafka 是一个分布式流式处理平台。

这到底是什么意思呢?

流平台具有三个关键功能:

1消息队列:发布和订阅消息流,这个功能类似于消息队列,这也是 Kafka 也被归类为消息队列的原因。
2容错的持久方式存储记录消息流: Kafka 会把消息持久化到磁盘,有效避免了消息丢失的风险·。
3流式处理平台: 在消息发布的时候进行处理,Kafka 提供了一个完整的流式处理类库。

Kafka 主要有两大应用场景:

1消息队列 :建立实时流数据管道,以可靠地在系统或应用程序之间获取数据。
2数据处理: 构建实时的流数据处理程序来转换或处理数据流。

关于 Kafka 几个非常重要的概念:

2Kafka 将记录流(流数据)存储在 topic 中。
3每个记录由一个键、一个值、一个时间戳组成。

Kafka 消息模型

题外话:早期的 JMS 和 AMQP 属于消息服务领域权威组织所做的相关的标准。但是,这些标准的进化跟不上消息队列的演进速度,这些标准实际上已经属于废弃状态。所以,可能存在的情况是:不同的消息队列都有自己的一套消息模型。

Kafka 的消息模型同时支持队列模型和发布-订阅模型。

队列模型(点对点模型)

使用队列(Queue)作为消息通信载体,满足生产者与消费者模式,一条消息只能被一个消费者使用,未被消费的消息在队列中保留直到被消费或超时。 比如:我们生产者发送 100 条消息的话,两个消费者来消费一般情况下两个消费者会按照消息发送的顺序各自消费一半(也就是你一个我一个的消费。)

队列模型存在的问题

假如我们存在这样一种情况:我们需要将生产者产生的消息分发给多个消费者,并且每个消费者都能接收到完成的消息内容。

这种情况,队列模型就不好解决了。很多比较杠精的人就说:我们可以为每个消费者创建一个单独的队列,让生产者发送多份。这是一种非常愚蠢的做法,浪费资源不说,还违背了使用消息队列的目的。

发布-订阅模型

发布-订阅模型主要是为了解决队列模型存在的问题。

发布订阅模型(Pub-Sub) 使用主题(Topic) 作为消息通信载体,类似于广播模式;发布者发布一条消息,该消息通过主题传递给所有的订阅者,在一条消息广播之后才订阅的用户则是收不到该条消息的

在发布 - 订阅模型中,如果只有一个订阅者,那它和队列模型就基本是一样的了。所以说,发布 - 订阅模型在功能层面上是可以兼容队列模型的。

Kafka 重要概念解读

Kafka 将生产者发布的消息发送到 Topic(主题) 中,需要这些消息的消费者可以订阅这些 Topic(主题),如下图所示:

上面这张图也为我们引出了,Kafka 比较重要的几个概念:

Producer(生产者) : 产生消息的一方。
Consumer(消费者) : 消费消息的一方。
Consumer Group(消费者组) :多个消费者实例共同组成的一个组,同时消费多个分区以实现高吞吐。
Broker(代理) : 可以看作是一个独立的 Kafka 实例,负责处理客户端请求以及对消息持久化。

同时,你一定也注意到每个 Broker 中又包含了 Topic 以及 Partition 这两个重要的概念:

Topic(主题) : Producer 将消息发送到特定的主题,Consumer 通过订阅特定的 Topic 来消费消息。
Partition(分区) : Partition 属于 Topic 的一部分。一个 Topic 可以有多个 Partition ,并且同一 Topic 下的 Partition 可以分布在不同的 Broker 上,这也就表明一个 Topic 可以横跨多个 Broker 。这正如我上面所画的图一样。

Kafka 中的 Partition(分区) 实际上可以对应成为消息队列中的队列。这样是不是更好理解一点?

⚠️注意 :Topic 下的每个 Partition 只从属于 Consumer Group 中的一个 Consumer,不可能出现 Consumer Group 中的两个 Consumer 负责同一个 Partition。相关阅读:《Kafka分区与消费者的关系》

另外,还有一点我觉得比较重要的是 Kafka 为 Partition 引入了多副本(Replica)机制。Partition 中的多个副本之间会有一个叫做 Leader 的家伙,其他副本称为 Follower。我们发送的消息会被发送到 Leader 副本,然后 Follower 副本才能从 Leader 副本中拉取消息进行同步。

生产者和消费者只与 leader 副本交互。你可以理解为其他副本只是 leader 副本的拷贝,它们的存在只是为了保证消息存储的安全性。当 leader 副本发生故障时会从 follower 中选举出一个 leader,但是 follower 中如果有和 leader 同步程度达不到要求的参加不了 leader 的竞选。

Kafka 的多分区(Partition)以及多副本(Replica)机制有什么好处呢?

1Kafka 通过给特定 Topic 指定多个 Partition, 而各个 Partition 可以分布在不同的 Broker 上, 这样便能提供比较好的并发能力(负载均衡)。
2Partition 可以指定对应的 Replica 数, 这也极大地提高了消息存储的安全性, 提高了容灾能力,不过也相应的增加了所需要的存储空间。

🌈 拓展一下(又一个常用的 Kafka 高可用小技巧):

多个 Kafka Broker 可以组成一个 Kafka Cluster(集群)。建议将不同的 Broker 分散运行在不同的机器上来提高可用性(有效避免单点故障)。

Zookeeper 在 Kafka 中的作用

要想搞懂 zookeeper 在 Kafka 中的作用 一定要自己搭建一个 Kafka 环境然后自己进 zookeeper 去看一下有哪些文件夹和 Kafka 有关,每个节点又保存了什么信息。一定不要光看不实践!

后面的文章中会介绍如何搭建 Kafka 环境,你且不要急,看了后续文章 3 分钟就能搭建一个 Kafka 环境。

下图就是我的本地 Zookeeper ,它成功和我本地的 Kafka 关联上(以下文件夹结构借助 idea 插件 Zookeeper tool 实现)。

ZooKeeper 主要为 Kafka 提供元数据的管理的功能。

从图中我们可以看出,Zookeeper 主要为 Kafka 做了下面这些事情:

1Broker 注册 :在 Zookeeper 上会有一个专门用来进行 Broker 服务器列表记录的节点。每个 Broker 在启动时,都会到 Zookeeper 上进行注册,即到/brokers/ids 下创建属于自己的节点。每个 Broker 就会将自己的 IP 地址和端口等信息记录到该节点中去
2Topic 注册 : 在 Kafka 中,同一个Topic 的消息会被分成多个分区并将其分布在多个 Broker 上,这些分区信息及与 Broker 的对应关系也都是由 Zookeeper 在维护。比如我创建了一个名字为 my-topic 的主题并且它有两个分区,对应到 zookeeper 中会创建这些文件夹:/brokers/topics/my-topic/Partitions/0、/brokers/topics/my-topic/Partitions/1
3负载均衡 :上面也说过了 Kafka 通过给特定 Topic 指定多个 Partition, 而各个 Partition 可以分布在不同的 Broker 上, 这样便能提供比较好的并发能力。 对于同一个 Topic 的不同 Partition,Kafka 会尽力将这些 Partition 分布到不同的 Broker 服务器上。当生产者产生消息后也会尽量投递到不同 Broker 的 Partition 里面。当 Consumer 消费的时候,Zookeeper 可以根据当前的 Partition 数量以及 Consumer 数量来实现动态负载均衡。
4…

需要说明的是,Kafka 2.8.0,移除了对 Zookeeper 的依赖(使用内嵌的KRaft替代了 ZooKeeper)。这样其实对于 Kafka 来说一个比较好的改进,我们再也不需要额外维护一套 ZooKpper 集群了。相关阅读:《Kafka为什么要抛弃ZooKeeper?》—yes

Kafka 如何保证消息的消费顺序?

我们在使用消息队列的过程中经常有业务场景需要严格保证消息的消费顺序,比如我们同时发了 2 个消息,这 2 个消息对应的操作分别对应的数据库操作是:更改用户会员等级、根据会员等级计算订单价格。假如这两条消息的消费顺序不一样造成的最终结果就会截然不同。

我们知道 Kafka 中 Partition(分区)是真正保存消息的地方,我们发送的消息都被放在了这里。而我们的 Partition(分区) 又存在于 Topic(主题) 这个概念中,并且我们可以给特定 Topic 指定多个 Partition。

每次添加消息到 Partition(分区) 的时候都会采用尾加法,如上图所示。Kafka 只能为我们保证 Partition(分区) 中的消息有序,而不能保证 Topic(主题) 中的 Partition(分区) 的有序。

消息在被追加到 Partition(分区)的时候都会分配一个特定的偏移量(offset)。Kafka 通过偏移量(offset)来保证消息在分区内的顺序性。

所以,我们就有一种很简单的保证消息消费顺序的方法:1 个 Topic 只对应一个 Partition。这样当然可以解决问题,但是破坏了 Kafka 的设计初衷。

Kafka 中发送 1 条消息的时候,可以指定 topic, partition, key,data(数据) 4 个参数。如果你发送消息的时候指定了 Partition 的话,所有消息都会被发送到指定的 Partition。并且,同一个 key 的消息可以保证只发送到同一个 partition,这个我们可以采用表/对象的 id 来作为 key 。

总结一下,对于如何保证 Kafka 中消息消费的顺序,有了下面两种方法:

11 个 Topic 只对应一个 Partition。
2(推荐)发送消息的时候指定 key/Partition。

当然不仅仅只有上面两种方法,上面两种方法是我觉得比较好理解的,

推荐阅读

●Apache Kafka using Keys for Partition:https://linuxhint.com/apache_kafka_partitions/
●Spring Boot and Kafka – Practical Configuration Examples:https://thepracticaldeveloper.com/2018/11/24/spring-boot-kafka-config/
●一文看懂大数据领域的六年巨变:https://www.infoq.cn/article/b8*EMm6AeiHDfI3SfT11





引用原文:在 Kafka 中,同一个Topic 的消息会被分成多个分区并将其分布在多个 Broker 上
一个 topic 可以分成多个 partition,而多个 partition 可以分布在多个 Broker 上。
g哥提到的要求和解决措施都是(强一致),如果需求本身不要求强一致,只是要求最终一致
看到还有两种解决方案:
1宽表: 创建一个表,将各种操作状态都记录到表中,最后返回整体状态就好
2消息补偿机制**:**另一个进行消费相同topic的数据,消息落盘,延迟处理。将消息与DB进行对比,如果发现数据不一致,再重新发送消息至主进程处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值