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

647 阅读8分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第六篇笔记。笔记的内容总结并归纳了黄庭坚老师讲述的走进消息队列课程。在学校的学习过程中很少遇到需要使用消息队列的情况,然而在真实的企业场景中,消息队列是不可或缺的中间件,因此,了解消息队列的本质以及其使用方式是非常有必要的。

案例引入

案例一:系统崩溃

1.PNG

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

案例二:服务能力有限

2.PNG

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

案例三:链路耗时长尾

3.PNG

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

案例四:日志存储

4.PNG

以上的四个场景,应该如何解决?

案例一:解决方案

解决方案:解耦

5.PNG

案例二:解决方案

解决方案:削峰

6.PNG

案例三:解决方案

解决方案:异步

7.PNG

案例四:解决方案

场景四:日志处理

8.PNG

什么是消息队列?

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

9.PNG

1.消息队列的前世今生

1.1 消息队列的发展历史

10.PNG

1.2 业界消息队列的对比

Kafka: 分布式的、分区的、多副本的日志提交服务

RocketMQ: 低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实际场景中应用较为广泛

Pulsar: 是下一代云原生分布式消息流平台,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计

BMQ: 和Pulsar架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对应的Kafka集群

2. 消息队列:Kafka

2.1 使用场景

11.PNG

2.2 如何使用Kafka

12.PNG

2.3 基本概念

13.PNG

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

基本概念-Offset

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

14.PNG

基本概念-Replica

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

15.PNG

2.4 数据复制

16.PNG

Controller用于计算集群的分区方式

2.5 Kafka架构

17.PNG

2.6 一条消息的自述

18.PNG

从一条消息的视角,看看为何Kafka能够支持如此高的吞吐?

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

回答: 显然这样的情况会让kafka的吞吐效率变得很慢

2.7 Producer-批量发送

19.PNG

思考: 如果消息量很大,网络带宽不够用应该如何解决?

2.7 Producer-数据压缩

20.PNG

2.8 Broker-数据的存储

21.PNG

2.8 Broker-消息文件结构

22.PNG

2.8 Broker-顺序写

23.PNG

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

2.8 Broker-如何找到消息

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

24.PNG

2.8 Broker-偏移量索引文件

目标:寻找offset=28

25.PNG

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

2.8 Broker-偏移量索引文件

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

26.PNG

2.8 Broker-时间戳索引文件

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

27.PNG

2.8 Broker-传统数据拷贝

28.PNG

2.8 Broker-零拷贝

29.PNG

2.9 Consumer-消息的接收端

30.PNG

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

2.9 Consumer-Low Level

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

31.PNG

思考一下,这种方式的缺点是什么? 1、不能够自动容灾 2、机器或者进程的启停,导致线上数据中断

2.9 Consumer-High Level

Rebalance

32.PNG

2.10 Consumer Rebalance

33.PNG

Kafka优势总结

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

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

2.11 Kafka-数据复制问题

34.PNG

2.12 Kafka-重启操作

35.PNG

2.13 Kafka-替换、扩容、缩容

36.PNG

思考一下,替换,扩容,缩容的流程应该是怎样的?

2.14 Kafka-负载不均衡

37.PNG

Kafka问题总结

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

38.PNG

3.消息队列-BMQ

3.1 BMQ简介

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

3.1 BMQ架构图

38.PNG

3.2 运维操作对比

39.PNG

3.3 HDFS写文件流程

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

40.PNG

3.4 BMQ文件结构

41.PNG

3.5 Broker-Partition状态机

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

42.PNG

3.5 Broker-写文件流程

43.PNG

3.5 Broker-写文件Failover

44.PNG

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

3.6 Proxy

45.PNG

3.7 多机房部署

46.PNG

3.8 BMQ-高级特性

47.PNG

3.9 泳道消息

开发流程:

48.PNG

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

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

BOE测试:

49.PNG

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

50.PNG

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

PPE验证 51.PNG

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

泳道应运而生

52.PNG

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

3.10 DataBus

53.PNG

如上图,左侧代码截图表示直接使用原生的SDK,右侧代码截图代表使用Databus。

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

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

54.PNG

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

3.11 Mirror

55.PNG

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

56.PNG

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

3.12 Index

57.PNG

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

58.PNG

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

3.13 Parquet

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

59.PNG

60、.PNG

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

总结

  • 1、BMQ的架构模型(解决Kafka存在的问题)
  • 2、BMQ读写流程(Failover机制,写入状态机)
  • 3、BMQ高级特性(泳道、Databus、Mirror Index、Parquet)

4. 消息队列-RocketMQ

使用场景

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

4.1 RocketMQ基本概念

61.PNG

本质上,Producer、Consumer和Broker三个部分,Kafka和RocketMQ是相同的。而Kafka中的Partition的概念在此处叫做ConsumerQueue 62.PNG

4.2 RocketMQ架构

63.PNG

首先,数据流也是通过Producer发送给Broker集群,再由Consumer进行消费

Kafka中,角色有Leader和follower,而在RocketMQ中,Broker节点有Master和Slave的概念

NameServer为集群提供轻量级服务发现和路由

4.3 存储模型

64.PNG

对于一个Broker来说,所有的消息会append到一个CommitLog上,然后按照不同的Queue,重新Dispatch到不同的Consumer中,这样Consumer就可以按照Queue进行拉取消费,但需要注意的是,这里的ConsumerQueue所存储的并非真实的数据,真实的数据其实仅仅存在于CommitLog中,该处村的仅仅是Queue中所有消息在CommitLog上的位置,相当于是该Queue的一个密集索引。

4.4 RocketMQ-高级特性

事务场景

65.PNG

我们需要保证,库存记录-1和消息队列应当放入一个事务中,保证最终的一致性

事务消息

66.PNG

类似于两阶段提交的处理流程,具体我也不是特别理解...

延迟发送

67.PNG

延迟消息

68.PNG

处理失败

69.PNG 关键在于如何处理失败的消息

消费重试和死信队列

70.PNG

小结

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