这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
一、消息队列介绍
1.消息队列的概念
指保存消息的一个容器,本质是一个队列,并且这个队列需要支持高吞吐、高并发和高可用。
2.消息队列发展历程
3.业界消息队列对比
- Kafta:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色
- RocketMQ:低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广
- Pulsar:是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计
- BMQ:和 Pulsar 架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的 Kafka 集群
二、Kafka
1.使用场景
一些搜索服务、直播服务、订单服务、支付服务以及用户行为和日志信息的系统监控数据,放入 Kafka 以便服务端进行处理。
2.基本概念
-
Cluster:物理集群,每个集群中可以建立多个不同的 Topic
-
Topic:逻辑队列,每一个不同的业务场景就是一个不同的 Topic,对于这个业务来说,所有的数据都存储在这个 Topic 中,不同 Topic 可以建立不同的 Topic
-
Partition:通常 Topic 会有多个分片,不同分片直接消息是可以并发来处理的,以此提高单个 Topic 的吞吐
-
Replica:分片的副本,分布在不同的机器上,可用来容灾,每个分片有多个 Replica,Leader Replica 将会从 ISR 中选出。Leader 对外服务,Follower 异步去拉取 Leader 的数据进行同步,如果 Leader 挂掉了,可以将 Follower 提升成 Leader 再对外进行服务
-
ISR:同步中的副本,对于 FoIIower 来说,始终和 Leader 是有一定差距的,但当这个差距比较小的时候,我们就可以将这个 Follower 副本加入到 ISR 中,不在 ISR 中的副本是不允许提升成 Leader 的
-
Offset:消息在 partition 内的相对位置信息,可以理解为唯一 ID,在 partition 内部严格递增
-
Producer:生产者,负责将业务消息送到 Topic 中
-
Consumer:消费者,负责消费 Topic 中的消息
-
ConsumerGroup:消费者组,不同组 Consumer 消费进度互不干涉
3.使用方法
-
创建集群
-
新增 Topic
在集群中创建 Topic,并且设置好分片数量
-
编写生产者逻辑
引入对应语言的 SDK,配置好集群和 Topic 等参数,初始化一个生产者,调用 Send 方法,将你的消息发送出去
-
编写消费者逻辑
引入对应语言的 SDK,配置好集群和 Topic 等参数,初始化一个消费者,调用 Poll 方法,你将收到你刚刚发送的消息
4.数据复制
上图代表着 Kafka 中副本的分布图。途中 Broker 代表每一个 Kafka 的节点,所有的 Broker 节点终组成了一个集群。
整个图表示,集群中包含了 4 个 Broker 机器节点,集群有两个 Topic,分别是 Topic1 和 Topic2,Topic1 有两个分片,Topic 2 有 1 个分片,每个分片都是三副本的状态。这其中有一个 Broker 同时扮演了 Controller的角色,Controller 是整个集群的大脑,负责对副本和 Broker 进行分配。
5.Kafka 架构
在集群的基础上,还有一个模块是 ZooKeeper,这个模块其实是存储了集群的元数据信息,比如副本的分配信息等等,Controller 计算好的方都会放到这个地方。
6.Kafka 特点
1.Producer
- Producer 让消息能够批量发送,以减少 IO 次数,从而加强发送能力
- Producer 让消息通过压缩,减少消息大小,目前支持 Snappy、Gzip、LZ4、ZSTD 压缩算法
2.Broker
- Broker 消息文件结构
-
Broker 采顺序写的方式进行写入,以提高写入效率
-
Broker 寻找消息
Consumer 通过发送 FetchRequest 请求消息数据,Broker 会将指定 Offset 处的消息按照时间窗口和消息大小窗口发送给 Consumer
寻找数据通过两种方法:
- 在 Broker 偏移量索引文件中,用二分找到小于目标 offset 的最大索引位置
- 在 Broker 时间戳索引文件中,用二分法找小于目标时间戳最大的索引位置,再通过寻找 offset 的方式找到最终数据。
-
Broker 零拷贝
Consumer 从 Broker 中读取数据,通过 sendfile 的方式,将磁盘读到操作系统内核缓冲区后,直接转到 socket buffer 进行网络发送。Producer 生产的数据持久化到 broker,采用 mmap 文件映射,实现顺 序的快速写入。
3.Consumer
-
High Level
High Level 用来解决 Partition 在 Consumer Group 中的分配问题,是一种高可用的消费方式。
简单的来说,就是在我们的 Broker 集群中,对于下同的 Consumer 来说,都会选取一台 Broker 当做 Coordinator,而 Coordinator 的作用就是帮 Group 进行分片的分配,也叫做分片的 rebalance。
使用这种方式, 如 Consumer Group 中发生宕机,或者有新的 Consumer 加入,整个 partition 和Consumer 都会重新进行分配来达到一个稳定的消费状态。
-
Rebalance
4.重启操作
-
当数据赶完成之后,我们要回切 leader,这一步叫做 prefer leader,这一步的目的是为了避免在一个集群长期运行后 , 所有的 leader 都分布在少数节点上,导致数据的不均衡。
还有一点,要避免并发的重启多台服务器,因为对某一分片来讲,可能所有的个分片都在这台机器上面,则会导致该集群处于不可用的状态。
-
若果是替换或者扩缩容,很多数据都要从 0 开始复制,将会有很大的时间成本。
虽然 Kafka 解决了作为消息队列的基本问题,但面对流量日益增大的场景也还是存在着一些问题,比如运维成本高、对于负载不均衡的场景,解决方案复杂、没有自己的缓存、完全依赖 Page Cache 以及 Controller 和 Coordinator 和 Broker 在同一进程中,大量 IO 会造成其性能的下降,对于这些问题,预计将在后面的学习中有着相对来说一些好的解决方案。