这是我参与「第五届青训营 」笔记创作活动的第22天
一:发展历程
1:问题引入
(1)系统崩溃
-
如果此时记录存储程序所在的机房被删库跑路了,上面这个流程会发生什么问题?
- 流程会直接卡住
-
解决方案:解耦
(2)服务能力有限
面对庞大的请求量,处理订单的服务一脸茫然,它的命运该何去何从?
- 解决方案:削峰
(3)链路耗时长尾
对于这个流程应该怎么优化来挽回这个暴躁的用户?
- 解决方案:异步
(4)日志存储
日志丢失如何修复问题?
解决方案:
2:消息队列简介
消息队列(MQ),指保存消息的一个容器,本质是个队列。但这个队列需要支持高吞吐,高并发,并且高可用。
3:发展历程
4:业界消息队列对比
- Kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色
- RocketMQ:低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广
- Pulsar:是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计
- BMQ:和Pulsar架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的Kafka集群
二:消息队列-kafka
1:使用场景
搜索服务
直播服务
订单服务
支付服务
↓
↓
kafka
2:如何使用kafka
创建集群→新增Topic→编写生产者逻辑→编写消费者逻辑
3:基本概念
(1)cluster
- Topic:逻辑队列,不同Topic可以建立不同的Topic
- Cluster:物理集群,每个集群中可以建立多个不同的Topic
- Producer:生产者,负责将业务消息发送到Topic中
- Consumer:消费者,负责消费Topic中的消息
- ConsumerGroup:消费者组,不同组 Consumer消费进度互不干涉
(2)offset
Offset :消息在 partition内的相对位置信息,可以理解为唯一ID,在 partition内部严格递增。
(3)replica
每个分片有多个 Replica,Leader Replica将会从ISR中选出。
4:数据复制
5:kafka架构
ZooKeeper:负责存储集群元信息,包括分区分配信息等
6:从一条消息看kafka流程
- 如果发送一条消息,等到其成功后再发一条会有什么问题?
- 太慢
7:producer-批量发送
- 思考题:如果消息量很大,网络带宽不够用,如何解决?
- 数据压缩
8:producer-数据压缩
9:broker-数据的存储
(1)broker消息文件结构
数据路径:/Topic/Partition/Segment/(log | index | timeindex l ...)
(2)broker-磁盘结构
移动磁头找到对应磁道,磁盘转动,找到对应扇区,最后写入。寻道成本比较高,因此 顺序写可以减少寻道所带来的时间成本。
(3)broker-顺序写
采用顺序写的方式进行写入,以提高写入效率
(4)broker-如何找到消息
Consumer通过发送 FetchRequest请求消息数据,Broker 会将指定Offset处的消息,按照时间窗口和消息大小窗口发送给Consumer,寻找数据这个细节是如何做到的呢?
(5)broker偏移量索引文件
目标:寻找 offset = 28
二分找到小于目标offset 的最大文件。
二分找到小于目标 offset的最大索引位置
(6)broker-时间戳索引文件
二分找到小于目标时间戳最大的索引位置,在通过寻找 offset的方式找到最终数据。
(7)broker-传统数据拷贝
(8)broker-零拷贝
10:Consumer-消息的接收端
如何解决Partition在 Consumer Group中的分配问题?
(1)Consumer-Low Level
通过手动进行分配,哪一个Consumer消费哪一个 Partition完全由业务来决定。
这种方式的缺点是什么?
(2)Consumer-High Level
11:Consumer Rebalance
12:可以帮助Kafka提高吞吐或者稳定性的功能有哪些?
- Producer:批量发送、数据压缩
- Broker:顺序写,消息索引,零拷贝
- Consumer: Rebalance
13:Kafka-数据复制问题
14:Kafka-重启操作
15:Kafka-替换、扩容、缩容
16:Kafka-负载不均衡
17:问题总结
- 运维成本高
- 对于负载不均衡的场景,解决方案复杂
- 没有自己的缓存,完全依赖 Page Cache
- Controller和 Coordinator和Broker在同一进程中,大量IO会造成其性能下降
三:消息队列-BMQ
1:简介
兼容Kafka 协议,存算分离,云原生消息队列
2:运维操作对比
3:HDFS 写文件流程
随机选择一定数量的 DataNode进行写入
4:BMQ文件结构
5:Broker-Partition状态机
保证对于任意分片在同一时刻只能在一个 Broker上存活
(1)Broker-写文件流程
(2)Broker-写文件Failover
如果 DataNode节点挂了或者是其他原因导致写文件失败,应该如何处理?
6:proxy
7:多机房部者
8:BMQ-高级特性
9:泳道消息
- BOE: Bytedance Offline Environment,是一套完全独立的线下机房环境
- PPE: Product Preview Environment,即产品预览环境
多个人同时测试,需要等待上一个人测试完成
每多一个测试人员,都需要重新搭建一个相同配置的Topic,造成人力和资源的浪费。
对于PPE的消费者来说,资源没有生产环境多,所以无法承受生产环境的流量
解决主干泳道流量隔离问题以及泳道资源重复创建问题。
10:Databus
- 直接使用原生SDK会有什么问题?
- 客户端配置较为复杂
- 不支持动态配置,更改配置需要停掉服务
- 对于latency不是很敏感的业务,batch效果不佳
- 简化消息队列客户端复杂度
- 解耦业务与Topic
- 缓解集群压力,提高吞吐
11:mirror
是否可以通过多机房部署的方式,解决跨Region读写的问题?
使用Mirror通过最终一致的方式,解决跨Region读写问题。
13:index
如果希望通过写入的Logld、Userld或者其他的业务字段进行消息的查询,应该怎么做?
直接在BMQ中将数据结构化,配置索引DDL,异步构建索引后,通过Index Query 服务读出数据。
14:parquet
Apache Parquet是Hadoop生态圈中一种新型列式存储格式,它可以兼容Hadoop生态圈中大多数计算框架(Hadoop、Spark等),被多种查询引擎支持(Hive、lmpala、Drill等)。
直接在BMQ中将数据结构化,通过 Parquet Engine,可以使用不同的方式构建 Parquet格式文件。
四:消息队列-RocketMQ
1:使用场景
例如,针对电商业务线,其业务涉及广泛,如注册、订单、库存、物流等;同时,也会涉及许多业务峰值时刻,如秒杀活动、周年庆、定期特惠等