【字节跳动】第十六讲 走进消息队列| 青训营笔记

2022-08-22 13:57:53 浏览数 (1)

讲师介绍

黄庭坚

  • 2020-2022 字节基础架构 消息队列团队
  • 负责离线消息队列自定义索引研发与离线日志存储相关研发工作

前言

  • 案例一:系统崩溃

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

  • 案例二:服务能力有限

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

  • 案例三:链路耗时长尾

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

目录

  1. 前世今生
  2. 消息队列-kafka
  3. 消息队列-BMQ
  4. 消息队列-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会有什么问题?

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

50.png

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

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 总结

  1. BMQ的架构模式(解决Kafka存在问题)
  2. BMQ读写流程(Failover机制,写入状态机)
  3. 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 小结

  1. RocketMQ的基本概念(queue,Tag)
  2. RocketMQ的底层原理(架构模型、存储模型)
  3. RocketMQ的高级特性(事务消息、重试和死信队列,延迟队列)

5. 课程总结

  • 前世今生:消息队列发展历程
  • Kafka:基本概念、架构设计、底层原理、架构缺点
  • BMQ:架构设计、底层原理、Kafka比较、高级特性
  • RocketMQ:架构设计、底层原理、高级特性

5.1 课后作业

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

0 人点赞