走进消息队列 | 青训营笔记

133 阅读7分钟
  1. 消息队列好处
  1. Q:存储程序故障导致系统崩溃,不能正常记录
    A:解耦。将记录先放入消息队列中,进而通过消息队列放入存储。这样即使存储程序故障,记录也在消息队列中,不会丢失
  2. Q:面对庞大的请求量,服务能力有限,一次只能同时处理一定量的请求
    A:削峰。先将请求放入消息队列,处理请求时,每次只获取对应量的请求进行处理
  3. Q:链路耗时长尾,处理一个请求所需步骤多、时间长
    A:异步。先将请求放入消息队列,再以异步的方式对多个步骤同时进行处理。
  4. Q:日志存储
    A:将日志写入消息队列,再通过日志组件对日志进行分析

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

Kafka

  1. 使用
    创建集群 -> 新增Topic -> 编写生产者逻辑(类似写入) -> 编写消费者逻辑(类似读取出)
  2. 基本概念
  • Topic:逻辑队列,不同的Topic可以建立不同的Topic(可以理解为每一个不同的业务场景就是一个Topic,业务里的所有数据都储存在这个Topic中)
  • Cluster:物理集群,每一个集群中可以建立多个不同的Topic,去处理不同的业务数据。
  • Producer:生产者,负责将业务消息发送到Topic中
  • Consumer:消费者,负责消费Topic中的消息
  • ConsumerGroup:消费者组,不同组Consumer消费进度互不干涉
  • Partition:Topic内的不同分区,不同的Partition在同一个Topic下是可以并发处理的 image.png
  • Offset:消息在partition内的相对位置信息,可以理解为唯一ID,在partition内部严格递增(保证消息在同一个partition内部的顺序性) image.png
  • 每个分片partition有多个Replica,以达到容灾的作用。消息的写入与读出先在Replica-Leader,Replica-Follower尽量与Leader保持一致,若差距悬殊,会被踢出ISR。 当Leader发生宕机时,会从ISR选取一个Follower成为Leader。 image.png
  • Broker:Cluster的节点
  • ZooKeeper:负责存储集群元信息,包括分区分配信息等 image.png
  1. 一条消息的自述
  • Producer
    • 批量发送:减少IO次数,从而加强发送能力 image.png
    • 数据压缩,防止消息量过大而导致Broker带宽不够用 image.png
  • Broker
    • 数据存储 image.png
    • 数据路径:/Topic/Partition/Segment/(log | index | timeindex | ...) image.png
    • 磁盘结构:移动磁头找到对应磁道,磁盘转动,找到对应扇区,最后写入。寻道成本比较高,因此顺序写可以减少寻道所带来的时间成本 image.png
    • 顺序写:末尾添加,可以提高写入效率,减少寻道时间
    • 寻找消息:Consumer通过发送FetchRequest请求消息数据,Broker会将指定Offset处的消息,按照时间窗口和消息大小窗口发送给Consumer image.png
      • 偏移量索引文件:二分找到小于目标offset的最大文件
      • 时间戳索引文件:二分找到小于目标时间戳最大的索引位置,再通过寻找offset的方式找到最终数据
    • 拷贝
      • 传统数据拷贝,开销较大 image.png
      • 零拷贝,降低拷贝次数,提高性能 image.png
  • Consumer
    • Consumer和partition分配问题:ConsumerGroup里的每个Cunsumer都会去拉取一个partition。解决方式有两种:
      1. Low Level:通过手动进行分配,哪一个Consumer消费哪一个partition完全由业务来决定。但不能自动容灾,若一个consumer挂了,其对应的partition对应流就断了;添加新consumer时再次分配partition比较麻烦。
      2. High Level:为每一个组提供一个Coordinator协调者(Rebalance),会自动感知进行分配
  1. 存在的问题
    1. 数据复制问题:重启、替换、扩容、缩容等操作都需要数据复制
    2. 负载不均匀,解决方案复杂
    3. 运维成本高
    4. 没有自己的缓存,完全依赖Page Cache
    5. Controller和Coordinator和Borker在同一进程中,大量IO会造成其性能下降

BMQ

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

  1. BMQ架构图(有点像读写分离) image.png
  2. 运维操作对比 - 数据复制 image.png
  3. BMQ文件结构 - 负载不均匀
    • Kafka中写入的是Leader,Follower再去追随数据,就可能导致Broker节点负载不均
    • BMQ是随机选取DataNode,打散在集群中,分布较为均匀
  4. Broker-Partition状态机:保证对于任意分片在同一时刻只能在一个Broker上存活
  5. Broker - 写文件流程
    • 可以在Buffer就进行返回消息:保持高吞吐,但丧失数据可靠性,因为还没有最终落盘
    • 可以在storage再进行返回:高数据可靠性,低吞吐
    • checkpoint:保持数据和索引相匹配,防止中途宕机 image.png
      • 写文件 Failover:如果datanode挂了或其他原因导致写文件失败,那就重新找个新节点
  6. Proxy
  • wait:根据数据大小窗口或时间窗口。防止请求频繁,降低io压力
    • 数据大小窗口:数据达到多少才返回给客户端
    • 时间窗口:到达规定的某个时间,即使数据达不到要求,也要返回
  • cache可以直接return数据给consumer,没有的话再去storage image.png
  1. 多机房部署
  • 防止有机房出现故障
  • proxy不会把所有的partition都分配给一个机房的Broker,防止多个机房同时处理同一个partition,而是会分配给所有机房不同的partition
  • 若其中一个机房崩了,则先找到另一个机房的proxy,将崩溃的机房的流量partition分配过来
  1. 高级特性

image.png

(1) 泳道消息
开发流程:开发 - BOE -PPE - Prod BOE:bytedance office environment,一套完全独立的线下机房环境
PPE:product preview environment,产品预览环境(测试、验证)

  • 产生原因:
    1. BOE测试:
      • 多个人同时测试,需要等待上一个人测试完成
      • 若想同时测试,就得重新搭建一个相同配置的Topic,造成人力和资源的浪费
    2. PPE验证:
      • 对PPE的消费者来说,资源没有生产环境多,所以无法承受生产环境的流量
  • 应运而生 - 泳道消息
    • 解决主干通道流量间隔问题以及泳道资源重复创建问题
    • BOE:每个请求都有标识,若从Topic中接收到不是自己的,会过滤掉。每个consumer只接受自己对应泳道的消息
    • PPE:指定泳道达到对应Topic,不用担心是否会被打爆 image.png

(2) Databus

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

(3) Mirror

  • 跨地区读写问题
    • 采用多机房部署的缺陷:跨地区,proxy到broker延迟大
    • 采用mirror通过最终一致的方式,用异步mirror到其他地区。异步延迟

(4)Index
消息查询:1.offset;2.timestamp
Q:希望通过写入的字段进行消息查询
A:直接在BMQ中将数据结构化,配置索引DDL,异步构建所以后,通过Index Query服务读出数据

(5)Parquet
是Hadoop生态圈中一种新型列式存储格式,它可以兼容Hadoop生态圈中大多数计算框架(Hadoop、Spark等),被多种查询引擎支持(Hive、Impala、Drill等)
直接在BMQ中将数据结构化,通过Parquet Engine,可以使用不同的方式构建Parquet格式文件

消息队列 - RocketMQ

  1. 基本概念
    image.png
  2. 架构 image.png
  3. 存储模型 存储的不是真实数据,而是一个类似于密集索引 image.png
  4. 高级特性
    (1) 事务消息 (2) 延迟队列 image.png (3) 消费重试和死信队列 image.png