讲师介绍
黄庭坚
- 2020-2022 字节基础架构 消息队列团队
- 负责离线消息队列自定义索引研发与离线日志存储相关研发工作
前言
- 案例一:系统崩溃
如果此时记录存储程序所在的机房被删库跑路了,上面的这个流程会发送什么问题?
- 案例二:服务能力有限
面对庞大的请求量,处理订单的服务一脸茫然,它的命运该何去何从?
- 案例三:链路耗时长尾
对于这个流程应该怎么优化来挽回这个暴躁的用户?
目录
- 前世今生
- 消息队列-kafka
- 消息队列-BMQ
- 消息队列-RocketMQ
1. 前世今生
1.1 消息队列发展历程
1.png
1.2 业界消息队列对比
- kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色(目前最常用)
- RocketMQ:低延迟、强一致、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广(阿里自研的)
- Pulsar:是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计
- BMQ:和Pulsar架构类似,存放分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的kafka集群
2. 消息队列-Kafka
2.1 使用场景
- 日志信息(通过离线的方式)
- Metrics数据(例如:QPS,程序执行的状态,执行时的一些耗时)
- 用户行为(使用软件时的操作例如:搜索、点赞、评论、收藏)
2.png
2.2 如何使用Kafka
创建集群 --> 新增 Topic --> 编写生产者逻辑 --> 编写消费者逻辑
2.3 基本概念
3.png
- Toplic:逻辑队列,不同Topic可以建立不同的Topic
- Cluster:物理集群,每个集群中可以建立多个不同的Topic
- Producer:生产者,负责将业务消息发送到Topic中
- Consumer:消费者,负责消费Topic中的消息
- ConsumerGroup:消费者组,不同组Consumer消息进度互不干涉
2.3.1 Offset
Offset:消息在partition内的相对位置信息,可以理解为唯一ID,在partition内部严格递增。
4.png
2.3.2 Replica
每个分片有多个Replica,Leader Replical将会从ISR中选出。
5.png
2.4 数据复制
6.png
2.5 Kafka 架构
7.png
ZooKeeper:负责存储集群元信息,包括分区分配信息等
2.6 一条消息的角度
8.png
从一条消息的视角,看看为什么Kafka 能支持这么高的吞吐?
思考:
9.png
如果发送一条信息,等到其成功后再发一条会有什么问题?
2.7 Producer
2.7.1 Producer-批量发送
10.png
批量发送可以减少IO次数,从而加强发送能力
可是出现了新的问题:如果消息量很大,网络带宽不够用,如何解决?
例如:我当前的服务器向前端展示一条视频,但是服务器的带宽(网速)不够怎么办?
2.7.2 数据压缩
11.png
通过压缩,减少消息大小,目前支持Snappy、Gzip、LZ4、ZSTD压缩算法
之前默认使用Snappy
目前通过测试的得出ZSTD是最好的也是最普遍的
推荐使用ZSTD的压缩算法
2.8 Broker
2.8.1 消息文件结构
12.png
数据路径:/Topic/Partition/Segment/(log | index | timeindex | ...)
2.8.2 磁盘结构
移动磁头转到对应的磁道,磁盘转动,找到对应扇区,最后写入。寻道成本比较高,因此顺序写可以减少寻道所带来的时间成本。
13.png
2.8.3 顺序写
14.png
采用顺序写的方式进行写入,以提高写入效率
2.8.4 如何找到消息
Consumer 通过发送 FetchRequest 请求消息数据,Broker会将指定Offset处的消息,按照时间窗口和消息大小窗口发送给Consumer,寻找数据这个细节是如何做到的呢?
15.png
2.8.4 偏移量索引文件
目标:寻找Offset = 28
16.png
二分找到小于目标offset的最大文件。
17.png
2.8.5 时间戳索引文件
二分找到小于目标时间戳最大的索引位置,再通过寻找offset的方式找到最终数据。
18.png
2.8.6 传统数据拷贝
19.png
2.8.7 零拷贝
20.png
2.9 Consumer
2.9.1 消息的接收端
21.png
如何解决Partition在Consumer Group中的分配问题?
2.9.2 Low Level
通过手动进行分配,哪一个Consumer消费哪一个Partition完全由业务来决定。
22.png
思考一下,这种方式的缺点是什么?
2.9.3 Consumer-High Level
23.png
Rebalance?
2.10 Rebalance
24.png
25.png
26.png
27.png
28.png
哪一些可以帮助Kafka提高吞吐或者稳定性的功能?
- Producer:批量发送、数据压缩
- Broker:顺序写,消息索引,零拷贝
- Consumer:Rebalance
2.11 Kafka 数据复制问题
29.png
2.12 Kafka-重启操作
30.png
2.13 KafKa-替换、扩容、缩容
31.png
思考:替换、扩容,缩容的流程应该是怎样的?
2.14 Kafka-负载不均衡
32.png
2.15 问题总结
- 运维成本高
- 对于负载不均衡的场景,解决方案复杂
- 没有自己的缓存,完全依赖Page Cache
- Controller和Coordinator和Broker在同一进程中,大量IO 会造成其性能下降
3 消息队列-BMQ
3.1 BMQ简介
兼容Kafka协议,存放分离,云原生消息队列
BMQ架构图
3.2 运维操作对比
34.png
3.3 HDFS写文件流程
随机选择一定数量的DataNode 进行写入
35.png
3.4 BMQ文件结构
Kafka
BMQ
3.5 Broker-Partition
3.5.1 状态机
38.png
保证对于任意分片在同一时刻只能在一个Broker上存活
3.5.2 写文件流程
39.png
3.5.3 写文件Failover
40.png
如果DataNode 节点挂了或者其他原因导致我们写文件失败,应该如何处理?
3.6 Proxy
41.png
3.7 多机房部署
42.png
3.8 BMQ-高级特性
43.png
3.9 泳道消息
开发流程
44.png
- BOE:Bytedance Offline Environment,是一套完全独立的线下机房环境
- PPE:Product Preview Environment, 即产品预览环境
45.png
多个人同时测试,需要等待上一个人测试完成
46.png
每多一个测试人员,都需要重新搭建一个相同配置的Topic,造成人力和资源的浪费。
47.png
对于PPE的消费者来说,资源没有生产环境多,所以无法承受生成环境的流量。
48.png
解决主干泳道流量隔离问题以及泳道资源重复创建问题。
3.10 Databus
49.png
直接使用原生SDK会有什么问题?
- 客户端配置较为复杂
- 不支持动态配置,更改配置需要停掉服务
- 对于latency不是很敏感的业务,batch效果不佳
50.png
- 简化消息队列客户端复杂度
- 解耦业务与Topic
- 缓解集群压力,提高吞吐
3.11 Mirror
51.png
思考一下,我们是否可以通过多机房部署的方式,解决跨Region读写的问题?
52.png
使用Mirror通过最终一致的方式,解决跨Region读写问题
3.12 Index
53.png
如果希望通过写入的LogId、UserId或者其他的业务字段进行消息的查询,应该怎么做?
54.png
直接在BMQ中将数据结构化,配置索引DDL,异步构建索引后,通过Index Query 服务读出数据。
3.14 Parquet
Apache Parquet是Hadoop生态圈中一种新型列式存储格式,它可以兼容Hadoop生态圈中大多数计算框架(Hadoop、Spark等),被多种查询引擎支持(Hive、Impala、Drill等)。
55.png
56.png
57.png
直接在BMQ中将数据结构化,通过Parquet Engine,可以使用不同的方式构建Parquet格式文件。
3.15 总结
- BMQ的架构模式(解决Kafka存在问题)
- BMQ读写流程(Failover机制,写入状态机)
- BMQ高级特性(泳道、Databus、Mirror、Index、Parquet)
4 消息队列-RocketMQ
4.1 使用场景
例如,针对电商业务线,其业务涉及广泛,如注册、订单、库存、物流等;同时,也会涉及许多业务峰值时刻,如秒杀活动、周年庆、定期特惠等
4.2 RocketMQ 基本概念
58.png
59.png
4.3 RocketMQ架构
60.png
4.4 存储模型
61.png
4.5 RocketMQ
4.5.1 RocketMQ-高级特性
RocketMQ的高级特性有哪些?
4.5.2 高级特性-事务场景
62.png
4.5.3 高级特性-事务消息
63.png
4.5.4 高级特性-延迟发送
64.png
4.5.5 高级特性-延迟消息
65.png
4.5.6 高级特性-处理失败
66.png
该如何处理失败的消息?
4.5.7 高级特性-消息重试和死信队列
68.png
4.5.8 小结
- RocketMQ的基本概念(queue,Tag)
- RocketMQ的底层原理(架构模型、存储模型)
- RocketMQ的高级特性(事务消息、重试和死信队列,延迟队列)
5. 课程总结
- 前世今生:消息队列发展历程
- Kafka:基本概念、架构设计、底层原理、架构缺点
- BMQ:架构设计、底层原理、Kafka比较、高级特性
- RocketMQ:架构设计、底层原理、高级特性
5.1 课后作业
- 手动搭建一个Kafka集群。
- 完成Hello World的发送与接收。
- 关闭其中一个Broker,观察发送与接收的情况,并写出,在关闭一个Broker后,Kafka集群会做哪些事情?