消息队列原理和实战 | 青训营笔记

100 阅读6分钟

这是我参与「第五届青训营 」笔记创作活动的第22天

一:发展历程

1:问题引入

(1)系统崩溃

image.png
  • 如果此时记录存储程序所在的机房被删库跑路了,上面这个流程会发生什么问题?

    • 流程会直接卡住
  • 解决方案:解耦

image.png

(2)服务能力有限

image.png

面对庞大的请求量,处理订单的服务一脸茫然,它的命运该何去何从?

  • 解决方案:削峰
image.png

(3)链路耗时长尾

image.png

对于这个流程应该怎么优化来挽回这个暴躁的用户?

  • 解决方案:异步
image.png

(4)日志存储

日志丢失如何修复问题?
解决方案:

image.png

2:消息队列简介

消息队列(MQ),指保存消息的一个容器,本质是个队列。但这个队列需要支持高吞吐,高并发,并且高可用。

image.png

3:发展历程

image.png

4:业界消息队列对比

  • Kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥较为出色
  • RocketMQ:低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广
  • Pulsar:是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计
  • BMQ:和Pulsar架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的Kafka集群

二:消息队列-kafka

1:使用场景

搜索服务 直播服务 订单服务 支付服务

image.png
kafka

2:如何使用kafka

创建集群→新增Topic→编写生产者逻辑→编写消费者逻辑

3:基本概念

(1)cluster

image.png

  • Topic:逻辑队列,不同Topic可以建立不同的Topic
  • Cluster:物理集群,每个集群中可以建立多个不同的Topic
  • Producer:生产者,负责将业务消息发送到Topic中
  • Consumer:消费者,负责消费Topic中的消息
  • ConsumerGroup:消费者组,不同组 Consumer消费进度互不干涉

(2)offset

Offset :消息在 partition内的相对位置信息,可以理解为唯一ID,在 partition内部严格递增。

image.png

(3)replica

每个分片有多个 Replica,Leader Replica将会从ISR中选出。

image.png

4:数据复制

image.png

5:kafka架构

image.png

ZooKeeper:负责存储集群元信息,包括分区分配信息等

6:从一条消息看kafka流程

image.png

image.png

  • 如果发送一条消息,等到其成功后再发一条会有什么问题?
    • 太慢

7:producer-批量发送

image.png

  • 思考题:如果消息量很大,网络带宽不够用,如何解决?
    • 数据压缩

8:producer-数据压缩

image.png

9:broker-数据的存储

image.png

(1)broker消息文件结构

image.png

数据路径:/Topic/Partition/Segment/(log | index | timeindex l ...)

(2)broker-磁盘结构

移动磁头找到对应磁道,磁盘转动,找到对应扇区,最后写入。寻道成本比较高,因此 顺序写可以减少寻道所带来的时间成本。

image.png

(3)broker-顺序写

image.png

采用顺序写的方式进行写入,以提高写入效率

(4)broker-如何找到消息

Consumer通过发送 FetchRequest请求消息数据,Broker 会将指定Offset处的消息,按照时间窗口和消息大小窗口发送给Consumer,寻找数据这个细节是如何做到的呢?

image.png

(5)broker偏移量索引文件

目标:寻找 offset = 28

image.png

二分找到小于目标offset 的最大文件。

二分找到小于目标 offset的最大索引位置

image.png

(6)broker-时间戳索引文件

二分找到小于目标时间戳最大的索引位置,在通过寻找 offset的方式找到最终数据。

image.png

(7)broker-传统数据拷贝

image.png

(8)broker-零拷贝

image.png

10:Consumer-消息的接收端

image.png

如何解决Partition在 Consumer Group中的分配问题?

(1)Consumer-Low Level

通过手动进行分配,哪一个Consumer消费哪一个 Partition完全由业务来决定。

image.png

这种方式的缺点是什么?

(2)Consumer-High Level

image.png

11:Consumer Rebalance

image.png

12:可以帮助Kafka提高吞吐或者稳定性的功能有哪些?

  • Producer:批量发送、数据压缩
  • Broker:顺序写,消息索引,零拷贝
  • Consumer: Rebalance

13:Kafka-数据复制问题

image.png

14:Kafka-重启操作

image.png

15:Kafka-替换、扩容、缩容

image.png

16:Kafka-负载不均衡

image.png

image.png

17:问题总结

  • 运维成本高
  • 对于负载不均衡的场景,解决方案复杂
  • 没有自己的缓存,完全依赖 Page Cache
  • Controller和 Coordinator和Broker在同一进程中,大量IO会造成其性能下降

三:消息队列-BMQ

1:简介

兼容Kafka 协议,存算分离,云原生消息队列

image.png

2:运维操作对比

image.png

3:HDFS 写文件流程

随机选择一定数量的 DataNode进行写入

image.png

4:BMQ文件结构

image.png

5:Broker-Partition状态机

image.png

保证对于任意分片在同一时刻只能在一个 Broker上存活

(1)Broker-写文件流程

image.png

(2)Broker-写文件Failover

image.png

如果 DataNode节点挂了或者是其他原因导致写文件失败,应该如何处理?

6:proxy

image.png

7:多机房部者

image.png

8:BMQ-高级特性

image.png

9:泳道消息

image.png

  • BOE: Bytedance Offline Environment,是一套完全独立的线下机房环境
  • PPE: Product Preview Environment,即产品预览环境

image.png

多个人同时测试,需要等待上一个人测试完成

image.png 每多一个测试人员,都需要重新搭建一个相同配置的Topic,造成人力和资源的浪费。

image.png 对于PPE的消费者来说,资源没有生产环境多,所以无法承受生产环境的流量

image.png 解决主干泳道流量隔离问题以及泳道资源重复创建问题。

10:Databus

image.png

image.png

  • 直接使用原生SDK会有什么问题?
    • 客户端配置较为复杂
    • 不支持动态配置,更改配置需要停掉服务
    • 对于latency不是很敏感的业务,batch效果不佳
image.png
  • 简化消息队列客户端复杂度
  • 解耦业务与Topic
  • 缓解集群压力,提高吞吐

11:mirror

image.png

是否可以通过多机房部署的方式,解决跨Region读写的问题?

image.png 使用Mirror通过最终一致的方式,解决跨Region读写问题。

13:index

image.png

如果希望通过写入的Logld、Userld或者其他的业务字段进行消息的查询,应该怎么做?

image.png

直接在BMQ中将数据结构化,配置索引DDL,异步构建索引后,通过Index Query 服务读出数据。

14:parquet

Apache Parquet是Hadoop生态圈中一种新型列式存储格式,它可以兼容Hadoop生态圈中大多数计算框架(Hadoop、Spark等),被多种查询引擎支持(Hive、lmpala、Drill等)。

image.png

image.png

直接在BMQ中将数据结构化,通过 Parquet Engine,可以使用不同的方式构建 Parquet格式文件。

四:消息队列-RocketMQ

1:使用场景

例如,针对电商业务线,其业务涉及广泛,如注册、订单、库存、物流等;同时,也会涉及许多业务峰值时刻,如秒杀活动、周年庆、定期特惠等

2:基本概念

image.png

image.png

3:架构

image.png

4:存储模型

image.png

5:高级特性

(1)事务场景

image.png

(2)事务消息

image.png

(3)延迟发送

image.png

(4)延迟消息

image.png

(5)处理失败:消费重试和死信队列

image.png

image.png