消息队列
简介
应对场景:
- 系统崩溃
- 服务能力有限
- 链路长尾耗时
- 使用日志恢复数据
解决方案:
- 解耦,将行为存在消息队列中,即使存储系统崩溃流程仍然正常执行
- 削峰,通过消息队列控制同时处理的请求数
- 异步,不通过长尾操作确定行为是否执行结束
- 日志分析,使用消息对列进行日志分析
由此可以导出 消息队列(MQ) 的基本概念:
指保存消息的一个容器,本质是个队列,但是需要支持高吞吐 高并发 高可用
发展历程:
flowchart TD
1(TIB) -- "1985,服务于金融机构和新闻机构"--> 2(IBM MQ/WebSphere) -- "1993,商业消息队列平台市场主要玩家" --> 3(MSMQ) -- "1997,微软" --> 4(JMS) -- "2001,本质是一套Java API"-->5(AMMQ/RabbitMQ) -- "2004发布规范,同年面世" --> 6(Kafka) -- "2010由Linked开源" --> 7(RocketMQ) -- "2011阿里中间件团队自研" --> 8(Pulsar)
业界常用的消息队列:
- Kafka : 分布式的 、 分区的 、 多副本的日志提交服务 , 在高吞吐场景下发挥较为出色
- RocketMQ : 低延迟 、 强一致 、 高性能 、 高可靠 、 万亿级容量和灵活的可扩展性 , 在一些实时场景中运用较广
- Pulsar: 是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计
- BMQ: 和 PuIsar 架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的 Kafka 集群
Kafka
使用场景
Kafka一般使用在离线的消息处理当中,比如处理各个服务产生的日志信息,以及程序运行过程中采集的一些metrics,来分析程序状态,其次是处理用户行为,也会放到消息队列里进行分析
如何使用
- 搭建Kafka集群
- 新建一个
Topic并设置分区 partition - 调用SDK编写生产者逻辑
- 调用SDK编写消费者逻辑
基本概念
Topic: Kafka中的逻辑队列,理解为一个不同的业务场景就是一个Topic,该业务的数据储存在该 Topic中
Partition: Topic可以进行分区,不同的区(即partition)可以并发处理,以此提高 Topic吞吐能力
Cluster: Kafka的物理集群,每个集群可以新建多个不同的 Topic
Producer: 生产者,负责将业务消息发送到 Topic中
Consumer: 负责消费 Topic中的消息
ConsumerGroup 消费者组,不同组的消费者互不干涉
位置:
Offset: 消息在 partition 内的相对位置信息,可以理解为唯一 ID,在 partition 内部严格递增。
Replica: 分片的副本,分布在不同的机器上,可用来容灾,Leader 对外服务,Follower异步去拉取leader的数据进行一个同步,如果 Leader挂掉了 , 可以将 Follower提升成 Leader再对外进行服务
ISR: 意思是同步中的副本(In-Sync Replicas),对于 Follower来说,始终和 Leader是有一定差距的,但当这个差距比较小的时候,我们就可以将这个 Follower副本加入到 ISR 中,不在 ISR 中的副本是不允许提升成 Leader 的
数据冗余存储示例:
分析:
图中 Broker代表每一个 Kafka的节点,所有的 Broker节点组成一个集群。集群包含4个 Broker节点,集群有两个 Topic,分别是 Topic1和 Topic2,1有两个分片,2有1个分片,每个分片都有三个副本。第二个 Broker同时也是 Controller,是整个集群的大脑,负责对副本和 Broker 进行分配
生产架构:
支持高吞吐和稳定性的手段
Producer:批量发送 数据压缩Broker:顺序写 消息索引 零拷贝Consumer:Rebalance
存在的问题
- 运维成本高
- 对于负载不均衡的场景,解决方案复杂
- 没有自己的缓存,完全依赖 Page Cache
- Controller 和 Coordinator 和 Broker 在同一进程中,大量 IO会造成其性能下降
BMQ
简介
BMQ 兼容 Kafka 协议,存算分离,云原生消息队列,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的 Kafka集群
架构:
注意点:
- 适配Kafka协议,很多概念共通或类似
- Controller Coordinator单独部署
- 多设置一层 Proxy Cluster
- 存算分离,将存储下放到分布式文件系统(BD内部是HDFS)
- Meta Storage System 代替Zoo Keeper
与Kafka的对比
运维:
| OP | Kafka | BMQ |
|---|---|---|
| 重启 | 需要数据复制,分钟级重启 | 重启后可直接对外服务,秒级完成 |
| 替换 | 需要数据复制,分钟级替换,甚至天级别 | 替换后可直接对外服务,秒级完成 |
| 扩容 | 需要数据复制,分钟级扩容,甚至天级别 | 扩容后可直接对外服务,秒级完成 |
| 缩容 | 需要数据复制,分钟级缩容,甚至天级别 | 缩容后可直接对外服务,秒级完成 |
BMQ的读写操作
- 随机选择指定数量的Datanode进行写入,不会导致负载不均衡
- 状态机机制用来保证不会出现同一个分片在两个Broker上同时启动的情况,另外也能够保证一个分片的正常运行
- 校验完成后,会把数据放入Buffer中,通过一个异步的writeThread 线程将数据最终写入到底层的存储系统当中
高级特性
- 泳道: 解决主干泳道流量隔离问题以及泳道资源重复创建问题
- Databus: 对原生SDK的封装,简化及动态配置,解耦业务和 Topic,缓解集群压力,提高吞吐
- Mirror: 解决跨Region读写问题
- Index: 直接在 BMQ 中将数据结构化,配置索引 DDL,异步构建索引后,通过 lndex Query服务读出数据
- Parquet: Apache parquet是 Hadoop生态圈中一种新型列式存储格式,它可以兼容 Hadoop生态圈中大多数计算框架(Hadoop,Spark等)被多种查询引擎支持
RocketMQ
应用场景
例如,针对电商业务线,其业务涉及广泛,如注册,订单,库存,物流等;同时,也会涉及许多业务峰值时刻,如秒杀活动,周年庆,定期特惠等
基本概念
| 名称 | Kafka | RocketMQ |
|---|---|---|
| 逻辑队列 | Topic | Topic |
| 消息体 | Message | Message |
| 标签 | Tag | |
| 分区 | Partition | ConsumerQuene |
| 生产者 | Producer | Producer |
| 生产者集群 | Producer Group | |
| 消费者 | Consumer | Consumer |
| 消费者集群 | Consumer Group | Consumer Group |
| 集群控制器 | Controller | Nameserver |
架构
高级特性
- 事务消息
- 重试和si信队列
- 延迟队列