这是我参与 「第四届青训营 」 笔记创作活动的第11天
消息队列概述
-
消息队列应用场景
-
MQ 消息通道
-
- EventBridge 事件总线
- 事件源:将云服务、自定义应用、SaaS应用等应用程序产生的事件消息发布到事件集
- 事件集:存储接收到的事件消息,并根据事件规则将事件消息路由到事件目标
- 事件目标:消费事件消息
Data Platform 数据流平台
-
提供流/批数据处理能力
-
各类组件提供各类 Connect
-
提供 Stream ing/function 能力
-
根据数据 schema 灵活的进行数据预处理
-
-
主流消息队列介绍
- RabbitMQ
- RocketMQ
- Kafka
- Pulsar
| RabbitMQ | RocketMQ | Kafka | Pulsar | |
|---|---|---|---|---|
| 推出时间 | 2007 | 2012 | 2010 | 2016 |
| 使用语言 | Erlang | Java | Scala/Java | Java |
| 单机吞吐量 | 一般 | 较高 | 高 | 高 |
| 延迟 | 低 | 低 | 一般 | 低 |
| 可用性(分片) | 高(主从架构) | 高(主从架构) | 非常高(分布式) | 非常高(分布式) |
| 一致性 | 较高 | 高 | 高 | 高 |
| 扩展性 | 较高 | 高 | 高 | 非常高 |
以上是4款比较流行的消息队列软件
Kafka 详解
-
Kafka 架构介绍
-
-
zookeeper
-
-
选举机制:Paxos机制
-
提供一致性:写入(强一致性)、读取(会话一致性)
-
提供可用性:一半以上节点存活即可读写
-
提供功能:watch机制、持久/临时节点能力
-
kafka 存储数据:
- BrokerMeta 信息(临时节点)
- Controller 信息(临时节点)
- Topic 信息(持久化节点)
- Config 信息(持久化节点)
-
-
Broker角色:
- 若干个Broker 节点组成 kafka 集群
- Broker 作为消息的接受模块,使用React 网络模块进行消息数据的接收
- Broker 作为消息的持久化模块,进行消息的副本复制以及持久化(从图可以看到,leader和follower是是分布在两个 broker中,leader和 follower 之间进行消息的同步,保证数据的持久化)
- Broker 作为高可用模块,通过副本间的 Failover 进行高可用保证
-
controller
-
选举
- broker 启动会尝试去 zk 中注册 controller 节点
- 注册上 controller 节点的 broker 即为 controller
- 其余 broker 会 watch controller 节点,节点出现异常则进行重新注册
-
作用
- broker 重启/宕机时,负责副本的 Failover切换
- Topic 创建/删除时,负责TopicMeta信息广播
- 集群扩缩容时,进行状态控制
- partition/Replica 状态机维护
-
coordinator介绍:
- 负责 topic-partition<->consumer 的负责均衡
- 根据不同的场景提供不同的分配策略
-
-
-
Kafka 高可用
-
高可用:
-
副本同步机制:
- 提供 ISR 副本复制机制,提供热备功能
- 写入端提供 ack=0,-1, 1 机制,控制副本同步强弱
-
副本切换机制
- 提供 clean/unclean 副本选举机制
-
-
kafka 副本 ISR 机制:
-
AR:Assign Replica ,已经分配的所有副本
-
OSR:
- OutSyncReplica
- 很久没有同步数据的副本
-
ISR:
- 一直都在同步数据的副本
- 可以作为热备进行切换的副本
-
kafka 写入 Ack 机制
-
Ack = 1:
- Leader 副本写入成功,Producer 即认为写成功
-
Ack = 0:
- OneWay 模式
- Producer 发送后即为成功
-
Ack = -1:
- ISR 中所有副本都成功,Producer 才认为写成功
-
-
kafka如何保证消息不丢?
-
Q1:
- 3副本情况下,如何结合 m in.in syn c.replica 以及 ack 的配置,来保证写入的 kafka 系统中的数据不丢失?
- 答案: m in.in syn c.replica 配置成 2 ,ack = -1,可以时刻保证你的系统中有两个副本是有完整数据的,你在进行切换的时候,势必会切换到一个数据多的副本上,可以保证数据的不丢失
-
Q2:
- 如果是 5 副本呢?(与上面的一样)
-
-
kafka 副本同步:
-
LEO:logEndOffset ,日志最末尾的数据,文件中最后一条数据
-
HW:
- ISR 中最小的 LEO 最为HW
- HW 的消息为 Consumer 可见的消息
-
-
kafka副本选举:(重要的)
-
clean 选举:
- 优先选取 ISR 中的副本作为 leader
- 如果 ISR 中无可用的副本,则 partition 不可用(必须在 ISR 中选副本)
-
Unclean 选举
- 优先选举 ISR中的副本作为leader
- 如果 ISR 中无可用的副本,则选择其他存活副本
-
-
-
-
-
Kafka 集群扩缩容
-
kafka集群扩缩容之后的目标:
-
topic维度:
- partition 在各个 broker 之间分布是均匀的
- 同一个 partition 的replica 不会分布在一台 broker
-
broker 维度
- broker 之间 replica 的数量是均匀的
-
-
-
扩容步骤:
-
扩容 broker 节点
- leader 副本写入成功,producer 即认为写成功
-
计算均衡的 replica 分布拓扑
- 保证 topic 的partition 在 broker 间分布均匀
- 保证 broker 之间的 replica 分布均匀
-
controller 负责新的副本分布元数据广播
- controller 将新的leader/follower 信息广播给 broker
-
broker 负责新副本的数据同步
- broker上有需要同步数据的副本则进行数据同步
-
-
缩容步骤:
-
计算均衡的 replica 分布拓扑
- 保证 topic 的partition 在 broker 间分布均匀
- 保证 broker 之间 replica 分布均匀
-
controller 负责新的副本分布元数据广播
- controller 将新的 leader/follower信息广播给 broker
-
broker 负责新副本的数据同步
- broker 上有需要同步数据的副本则进行数据同步
-
下线缩容的broker节点
- 数据同步完毕之后下线缩容的broker节点
-
-
kafka 集群扩缩容问题”
- 扩缩容时间长:涉及到数据迁移,在生产环境中一次扩缩容可能要迁移TB 甚至 PB 的数据
- 扩缩容期间集群不稳定:保证数据的完整性,往往会从最老的数据进行同步,这样会导致集群时刻处于从磁盘中读取数据的状态,disk/net/cpu 负载都会比较高
- 扩缩容期间无法执行其他操作:在一次扩缩容操作结束之前,无法进行其他运维操作(扩缩容)
-
-
Kafka 未来演进之路
-
kafka去除zk依赖
-
依赖 zookeeper 存在问题:
- 元数据存取困难:元数据的存取过于困难,每次重新选举的 controller 需要把整个集群的元数据重新 restore ,非常的耗时且影响集群的可用性
- 元数据更新网络开销大:整个元数据的更新操作也是以全量推的方式进行,网络的开销也会非常大
- 强耦合违背软件设计原则:zookeeper 对于运维来说,维护zookeeper 也需要一定的开销,并且 kafka 强耦合与zk也并不好,还得时刻担心宕机问题,违背软件设计的高聚合、低耦合的原则
- 网络分区复杂度高:zookeeper 本身并不能兼顾到broker 与 broker 之间通信的状态,这就会导致网络分区的复杂度成几何倍数增长
- 并发访问 ZK 问题多:zookeeper 本身并不能兼顾到broker 与 broker 之间通信的状态,这就会导致网络分区的复杂度成几何倍数增长
-
-
kafka 依赖 KRaft:
- process.Roles = Broker:服务器在 Kafka 模式下充当 Broker
- process.Roles = Controller:服务器在 Kafka 模式下充当 Controller
- Process.Roles = Broker,Controller:服务器在 KRaft 模式下充当 Broker 和 Controller
- Process.Roles = null:那么集群就假定是运行在 Zookeeper 模式下
-
-
Kafka 运维/调优经验介绍(字节:2.3.1)
-
单机吞吐
-
参数配置:
-
扩缩容优化
-
- 指标可视化
- 
Pulsar 详解
-
Pulsar 架构介绍(具备了kafka不具备的功能)
-
-
pulsar proxy:
-
pulsar 客户端连接集群的两种方式:
- pulsar client —>broker
- pulsar client->proxy
-
pulsar proxy 的作用及应用场景
- 部分场景无法知道 broker 地址,如云环境
- proxy 提供类似 GateWay 代理能力,解耦客户端和 broker ,保障 broker 安全
-
-
pulsar broker:
-
-
Pulsar Broker 无状态组件,负责运行两个模块
-
Http 服务器
- 暴露了 restful 接口,提供生产者和消费者 topic 查找 api
-
调度分发器
- 异步的 tcp 服务器,通过自定义二进制协议进行数据传输
-
-
Pulsar Broker 作为数据层代理
-
Bookie通讯
- 作为 Ledger 代理负责和 Bookie 进行通讯
-
流量代理
- 消息写入 Ledger 存储到 Bookie(Java写的)进行持久化存储
- 消息缓存在堆外,负责快速响应
-
-
pulsar storage
-
-
Pulsar 数据存储 Segment 在不同存储中的抽象
- 分布式 Joumal 系统(Bookeeper)中为 Joumal/Ledger
- 分布式文件系统(GFS/HDFS) 中为文件
- 普通磁盎中为文件
- 分布式 Blob 存储中为 Blob
- 分布式对象存储中为对象
-
定义好抽象之后,即可实现多介质存储
-
L1(缓存):
- Broker 使用堆外内存短智存储消息
- 适用于 Tail-Read 读场景
-
L2(Bookkeeper):
- Bookkeeper 使用Qurom 写,能有效降低长尾,latency
- 适用于 Catch-Up 较短时间内的较热数据
-
L3(S3等冷存):
- 存储成木低;扩展性好
- 适用于 Catch-Up 长时间内的冷数据
-
-
-
pulsar function (轻量级计算框架)
-
-
-
bookeeper整体架构
- 在内存中进行一个聚合,之后在写入磁盘中-
bookkeeper 基本概念:
- Ledger: BK 的一个基本存储单元,BK Client 的读亏操作都是以 Ledger为粒度的
- Fragment: BK 的最小分布单元 (实际上也是物理上的最小存储单元),也是 Ledger 的组成单位,默认情况下
- Ledger 会对应的一个Fragment(—个 Ledger 也可能由多个Fragment 组成)
- Entry:每条日志都是一个Entry,它代表一个record,每条record 都会有一个对应的 entry id
-
- bookkeeper 新建 Ledger
-
- Ensemble size(E):一个Ledger 所涉及的 Bookie 集合
- Write Quorum Size(Qw):副本数
- Ack Quorum Size(Qa):写请求成功需要满足的副本数
bookkeeper Ledger 分布
- 从 Bookie Pool挑选 Bookies 构成 Ensemble
- Write Quorum Size 决定发送给哪此 Bookies
- Ack Quorum Size 决定收到几个 Ack 即为成功
bookkeeper 写一致性
bookkeeper读一致性
所有的 Reader 都可以安全读取 Entry 1D 小于或者等于 LAC 的记录,从而保证 reader 不会读取末确认的数据,从而保证了reader 之间的一致性 bookkeeper读写分离
写入优化
写入时,不但会写入到 Joural 中还会写入到缓存(memtable)中,定期会做刷盘(刷盘前会做排序,通 过聚合+排序 优化读取性能)
读取优化
先读 Memtable,没命中再通过索引读磁盘Ledger Device 中会维护一个索引结构,存储在 RocksDB中,它会将(Ledgerld, Entryld) 映射到(EntryLogld,文件中的偏移量)
bookkeeper with pulsar
Topic-Partition:
Topic 由多个 partition 组成 Partition 由多个 segment 组成 Segment 对应 Ledger
可以发现:
Partition <->Broker 之间只是映射关系 Broker 在扩缩容的过程中只需要更改映射即可
-
Pulsar 特性介绍
-
Pulsar vs Kafka
周边和生态
-
周边生态概览
-
Pulsar IO
-
Kafka Schema
-
Pulsar SQL