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

171 阅读6分钟

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

一、本堂课重点知识

今天主要的学习内容是消息队列原理与实战相关知识。

二、详细知识点介绍

什么是消息队列?

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

1. 前世今生

image.png

1.1 业界消息队列对比

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

2. Kafka

2.1 使用场景

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

2.2 如何使用Kafka

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

2.3 基本概念

  • Topic:逻辑队列,不同Topic可以建立不同的Topic
  • Cluster:物理集群,每个集群中可以建立多个不同的Topic
  • Producer:生产者,负责将业务消息发送到Topic中
  • Consumer:消费者,负责消费Topic中的消息
  • ConsumerGroup:消费者组,不同组Consumer消费进度互不干涉
  • Offset:消息在partition内的相对位置信息,可以理解为唯一D,在partition内部严格递增
  • Replica:每个分片有多个Replica,Leader Replica将会从ISR中选出

2.4 数据复制

image.png

2.5 Kafka架构

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

2.6 Producer

  • 批量发送
  • 数据压缩

2.7 Broker

  • 数据的存储
    • 消息文件结构
    • 磁盘结构
    • 顺序写

如何找到消息?

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

  • 偏移量索引文件

    • 目标:寻找offset=28
    • 二分找到小于目标offset的最大文件
    • 二分找到小于目标offset的最大索引位置
  • 时间戳索引文件

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

image.png

  • 零拷贝

image.png

2.8 Consumer

消息的接收端

  • Low Level
    • 通过手动进行分配,哪一个Consumeri消费哪一个Partition完全由业务来决定
  • High Level

  • 数据复制问题
  • 重启操作
  • 替换、扩容、缩容
  • 负载不均衡

问题总结

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

3. BMQ

3.1 简介

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

3.2 运维操作对比

具体操作KafkaBMQ
重启需要数据复制,分钟级重启重启后可直接对外服务,秒级完成
替换需要数据复制,分钟级重启,甚至天级别替换后可直接对外服务,秒级完成
扩容需要数据复制,分钟级重启,甚至天级别扩容后可直接对外服务,秒级完成
缩容需要数据复制,分钟级重启,甚至天级别缩容后可直接对外服务,秒级完成

3.3 HDFS写文件流程

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

3.4 BMQ文件结构

image.png

3.5 Broker

  • Partition状态机

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

  • 写文件流程

image.png

3.6 Proxy

image.png

3.7 多机房部署

image.png

3.8 高级特性

image.png

3,9 泳道消息

开发 \Rightarrow BOE \Rightarrow PPE \Rightarrow Prod

  • BOE:Bytedance Offline Environment,是一套完全独立的线下机房环境

  • PPE:Product Preview Environment,即产品预览环境、

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

  • 并行:每多一个测试人员,都需要重新搭建一个相同配置的Topc,造成人力和资源的浪费。

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

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

3.10 Databus

直接使用原生SDK会有什么问题?

  1. 客户端配置较为复杂
  2. 不支持动态配置,更改配置需要停掉服务
  3. 对于latency不是很敏感的业务,batch效果不佳

  1. 简化消息队列客户端复杂度
  2. 解耦业务与Topic
  3. 缓解集群压力,提高吞吐

3.11 Mirror

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

3.12 Index

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

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

3.14 Parquet

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

4. RocketMQ

4.1 使用场景

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

4.2 基本概念

image.png

4.3 RocketMQ架构

image.png

4.4 高级特性

  • 事务场景
    • 最终一致性
  • 事务消息
  • 延迟发送
  • 延迟消息
  • 消费重试和死信队列

三、实践练习例子

如何解决如下四个问题

  • 案例一:系统崩溃
    • 解耦
  • 案例二:服务能力有限
    • 削峰
  • 案例三:链路耗时长尾
    • 异步
  • 案例四:日志存储
    • 日志处理

从一条消息的视角,看看为什么Kafka能支撑这么高的吞吐?

image.png


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

image.png


如果消息量很大,网络带宽不够用,如何解决?

image.png

image.png


可以帮助Kafka提高吞吐或者稳定性的功能?

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

四、课后个人总结

学习到了更多消息队列原理与实战的相关知识。

  1. 手动搭建一个Kafka集群。
  2. 完成Hello World的发送与接收。
  3. 关闭其中一个Broker,观察发送与接收的情况,并写出,在关闭一个Broker后,Kafka集群会做哪些事情?

五、引用参考