前言
相信大家都或多或少听过消息队列这个组件,在互联网中各行各业发挥着至关重要的作用但是在大学课程当中却少有提及。现在一起了解一下在工业中比较成熟的消息队列,他的底层原理、架构设计以及高级特色。
情景模拟
案例一:系统崩溃
graph TB
id5((O.o))-->搜索直播间 --> 搜索行为记录 -->记录存储x
搜索行为记录 --> 点击商品 -->点击行为记录
点击行为记录 --> 记录存储x
如果此时记录存储程序所在的机房被删库跑路了,上面这个流程会发生什么问题?
- 解决方案:解耦
graph TB
id5((O.o))-->搜索直播间 --> 搜索行为记录 -->消息队列
搜索行为记录 --> 点击商品 -->点击行为记录
点击行为记录 --> 消息队列
消息队列 --> 存储服务
案例二:服务能力有限
graph TD
id5((多名用户)) ==>发起订单 --只能同时处理10订单请求--> 处理订单
面对庞大的请求量,处理订单的服务一脸茫然,它的命运该何去何从?
- 解决方案:削峰
graph TD
id5((多名用户)) ==>发起订单 -->消息队列 --只能同时处理10订单请求--> 处理订单
案例三:链路耗时长尾
graph TD
id5((O.o)) -->发起订单 --5ms--> 库存记录-1 --100ms--> 订单记录+1 --100ms--> 通知商家 --30s--> id5((O.o))
对于这个流程该怎么优化来挽回这个暴躁的用户?
- 解决方案:异步
graph TD
id5((O.o)) -->发起订单 --5ms--> 消息队列
消息队列 --50ms--下单成功-->id5((O.o))
消息队列 --100ms--> 订单记录+1
消息队列 --100ms--> 库存记录-1
消息队列 --30s--> 通知商家
案例四:日志如何处理
有服务器坏掉了,本地日志丢失了,没有本地日志如何修复刚刚发生的系统崩溃问题...
- 解决方案
graph LR
Log --> 消息队列 --> LogStash --> ES --> Kibana
前世今生
消息队列发展历程
业界消息队列对比
- Kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色
- RocketMQ:低延时、强一致、高性能、高可靠、亿万级容量和灵巧的可扩展性,在一些实时场景中运用较广
- Pulsar:是下一代云原生分别是消息流平台,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计
- BMQ:和Pulsar架构类似,存放分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的kafka集群
Kafka
将围绕着 kafka使用场景,业务日志、用户行为数据、Metrics 数据展开,介绍一条消息从生产到消费的处理流程。
1.使用场景
2.如何使用Kafka
graph LR
创建集群 --> 新增Topic --> 编写生产者逻辑--> 编写消费者逻辑
3.基本概念
Topic: 逻辑队列,不同 Topic 可以建立不同的 TopicCluster: 物理集群,每个集群中可以建立多个不同的 TopicProducer: 生产者,负责将业务消息发送到 Topic 中Consumer: 消费者,负责消费 Topic 中的消息ConsumerGroup: 消费者组,不同组 Consumer 消费进度互不干涉Offset: 消息在 partition 内的相对位置信息,可以理解为唯一ID,在 partition 内部严格递增- Replica
每个分片有多个Replica,Leader Replica将会从ISR中选出。
4.数据复制
5.Kafka架构
Zookeeper:负责存储集群元信息,包括区分分配信息等。
6.一条消息的自述
从一条消息的视角,看看为什么Kafka能支撑这么高的吞吐?
如果发送一条消息,等到其成功后再发一条会有什么问题?
graph LR
Producer --Message--> Broker
Broker --Success--> Producer
7.Producer
批量发送
批量发送可以减少IO次数,从而加强发送能力
数据压缩
通过压缩,减少消息大小,目前支持Snappy、Gzip、LZ4、ZSTD压缩算法
8.Broker
1)Broker-数据的存储
2)Broker-消息文件结构
数据路径: /Topic/Partition/Segment/(log l index I timeindex l ...)
3)Broker-磁盘结构
移动磁头找到对应磁道,磁盘转动,找到对应扇区,最后写入。寻道成本比较高,因此顺序写可以减少寻道所带来的时间成本
4)Broker-顺序写
采用顺序写的方式进行写入,以提高写入效率
5)Broker-如何找到消息
Consumer 通过发送 FetchRequest 请求消息数据,Broker 会将指定 Offset 处的消息,按照时间窗口和消息大小窗口发送给 Consumer,寻找数据这个细节是如何做到的呢?
6)Broker-偏移量索引文件
目标: 寻找 offset = 28
二分找到小于目标 offset 的最大文件
7)Broker-时间戳索引文件
二分找到小于目标时间戳最大的索引位置,在通过寻找 offset 的方式找到最终数据
8)Broker-传统数据拷贝
9)Broker-零拷贝
Consumer
1)Consumer-消息的接收端
2)Consumer-Low Level
通过手动进行分配,哪一个 Consumer消费哪一个 Partition 完全由业务来决定
3)Consumer-High Level
10.Consumer Rebalance
11.Kafka操作
1)Kafka-数据复制问题
2)Kafka-重启操作
3)Kafka-替换、扩容、缩容
4)Kafka-负载不均衡
13.Kafka-问题总结
- 运维成本高
- 对于负载不均衡的场景,解决方案复杂
- 没有自己的缓存,完全依赖 Page Cache Controller 和 Coordinator和Broker 在同一进程中,大量 IO会造成其性能下降
BMQ
基于 Kafka 在使用中遇到问题,引出 BMQ 架构,了解 BMQ 各模块在实际应用中如何工作以及 BMQ 多机房容灾相关内容。
1.BMQ简介
兼容Kafka协议,存算分离,云原生消息队列
2.运维操作对比
| 具体操作 | Kafka | BMQ |
|---|---|---|
| 重启 | 需要数据复制,分钟级重启 | 重启后可直接对外服务,秒级完成 |
| 替换 | 需要数据复制,分钟级替换,甚至天级别 | 替换后可直接对外服务,秒级完成 |
| 扩容 | 需要数据复制,分钟级扩容,甚至天级别 | 扩容后可直接对外服务,秒级完成 |
| 缩容 | 需要数据复制,分钟级缩容,甚至天级别 | 缩容后可直接对外服务,秒级完成 |
3.HDFS 写文件流程
4.文件结构对比
5.Broker—Partition状态机
6.Broker-写文件流程
7.Proxy
8.多机房部署
9.BMQ-高级特性
10.泳道消息
11.Databus
12.Mirror
思考一下,我们是否可以通过多机房部署的方式,解决跨Region读写的问题?
13.Index
如果希望写入的Logld、Userld或其他的业务字段进行消息的查询,应该怎么做?
直接在BMQ中将数据结构化,配置索引DDL,异步构建索引后,通过Index Query服务读出数据。
14.Parquet
Apache Parquet是Hadoop生态圈中一种新型列式存储格式,它可以兼容 Hadoop 生态圈中大多数计算框架(Hadoop、Spark等),被多种查询引擎支持(Hive、Impala、Drill等)。
RocketMQ
使用场景: 例如,针对电商业务线,其业务涉及广泛,如注册、订单、库存、物流等;同时,也会涉及许多业务峰值时刻,如秒杀活动、周年庆、定期特惠等