走进消息队列
几个案例:
-
系统崩溃
- 比如底层数据库出现故障
- 解决方案:解耦
-
服务能力有限
- 面对庞大的请求,处理能力有限
- 解决方案:削峰
-
链路耗时长
- 在某一步等待时间久
- 解决方案:异步
-
日志存储
什么是消息队列?
保存消息的一个容易,本质作为一个队列,需支持高吞吐,高并发,高可用。
发展历程
一些常见的消息队列产品:
-
Kafka
- 分布式,分区的,多副本的日志提交服务
- 高吞吐场景出色
-
RocketMQ
- 实时场景
-
Pulsar
- 云原生分布式消息流平台
-
BMQ
- 与Pular架构类似
Kafka
使用场景:
使用:
- 创建集群
- 新增Topic
- 编写生产者逻辑
- 编写消费者逻辑
基本概念
-
Topic
- 逻辑队列,可以理解成每一个不同的业务场景就是一个不同的Topic
-
Cluster
- 物理集群,每个集群中可以新建多个不同的topic
-
Producer
-
Consumer
-
ConsumerGroup
- 不同组的消费者进度互不干涉
-
Parathion
- 通常topic会有多个分片,不同的分片直接消息是可以并发来处理的,这样就提高了单个topic的吞吐
Offset: 消息在Partition中的相对位置信息,可以理解为唯一ID,在partition内部严格递增。对于每个partition来说,每一条消息都有一个唯一的offset。
Replica: 每个分片有多个的Replica, Leader Replica将从ISR中选出。
图中表示Kafka中副本的分布图。每个Broker代表集群一个节点,一共有4个broker节点,集群有两个Topic,分别是Topic1和Topic2。Topic1有两个分片,Topic2有一个分片。每个分片都是三副本状态。broker-controller是整个集群的大脑,负责对副本和broker进行分配。
架构
Zookeeper其实是存储了集群的元数据信息,如副本的分配信息等。
消息流程
分别从三个角度看待:
-
Producer
- 批量发送
- 数据压缩
-
Broker
- 顺序写,消息索引,零拷贝
-
Consumer
- Rebalance
Producer消息发送
在Producer阶段考虑一个问题,消息单条发送会有什么问题?
答:批量发送
那如果消息量很大,带宽不够用,怎么办?
答:数据压缩
Broker消息存储
消息文件结构:
为了提高写入消息,写入磁盘的时候采用的是追加写的方式
Comsumer发送请求消息的数据,broker会将指定offset处的消息,按照时间窗口和消息大小窗口发送给consumer。
另一个重要的点是,在消息发送给consumer的过程中做到高效,需要减少拷贝次数。(此处采用mmap文件映射,实现顺序快速写入)
Consumer接收消息
如何解决 partition 在 consumer group 中的分配问题?
-
手动分配
- 简单,但是没有容灾能力,如果一个consumer挂掉了,那么他接收的分片消息就停止了。
-
自动分配,在Broker集群中,对不同的consumer group,都会选一台broker当作coordinator,帮助进行分片的分配
这里值得注意的是有一个Rebanlance策略
缺点
-
运维成本高
- 对于升级节点,只能一个一个节点升级,时间成本较高。
-
对于负载不均衡场景,解决方案复杂
-
没有自己的缓存,完全依赖 Page Cache
-
Controller 和 Coordinator 和 Broker在同一个进程中,大量I/O会造成性能下降。