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

154 阅读8分钟

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

这是我参与「第五届青训营 」笔记创作活动的第14天。注:笔记大部分图片内容及代码段为青训营课程视频提供,仅交流,不得做个人使用

一、本课主要内容

消息队列原理

二、本节详细知识点

消息队列原理
-问题场景与解决思路
-含义
-消息队列前世今生
-业界消息队列对比
业界常见消息队列
Kafka、BMQ 、RocketMQ

1消息队列原理

1.1 场景案例

  • 系统崩溃

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

  • 服务能力有限

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

  • 链路长尾耗时

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

  • 日志存储

image.png 服务器宕机导致本地日志丢失如何修复问题?

1.2消息队列解决问题

  • 系统崩溃时-解藕

image.png

  • 服务能力有限时- 削峰

image.png

  • 链路长尾耗时-异步

image.png

  • 日志处理

image.png

1.3 消息队列简述

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

image.png

1.4消息队列发展历程

image.png

1.5业界消息队列对比

image.png

2kafka

2.1使用场景

image.png Metrics:程序状态记录

2.2如何使用kafka

image.png

2.3基本概念

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

image.png

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

image.png

  • replic(副本数) 每个分片有多个 Replica, LeaderReplica将会从ISR中选出。

image.png ISR,一个kakfa特质,同步中的副本

  • 数据复制

image.png Broker:节点。Partition:分区(分片)。Controller:控制整个集群

2.4 Kafka架构

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

2.5 一条消息的自述

从一条消息的视角,看看为什么Kafka 能支撑这么高的吞吐? image.png 按照P->B->C的过程

  • 思考
    如果发送条消息等到其成功后再发下一条会有什么问题? image.png

2.6Producer

  • 批量处理 image.png 思考题:如果消息量很大,网络带宽不够用,如何解决?
  • 数据压缩 通过压缩减少消息大小,目前支持Snappy、 Gzip、 LZ4、 ZSTD压缩算法

image.png 推荐使用ZSTD

Broker-数据的存储

如何存储数据? image.png

  • Broker-消息文件结构

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

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

image.png

  • Broker-顺序写

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

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

image.png

  • Broker-偏移量索引文件 目标:寻找 offset 28 image.png 二分找到小于目标offset的最大文件

image.png 分找到小于目标 offset 的最大索引位置

  • Broker-时间戳索引文件 二分找到小于目标时间截最大的索引位置,再通过寻找 offset 的方式找到最终数据。

image.png

  • Broker(优化)-传统数据拷贝 传统路径很长,开销很大 image.png
  • Broker(优化)-零拷贝 降低了三次的内存拷贝次数 image.png ?segment file ?mmap

consumer-消息的接收端

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

image.png

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

image.png 这样的分配方式的缺点是? 容灾问题,单一consumerN崩溃时无法及时维护其Patition;新增consumer不易。

  • consumer-自动分配High Level broker担任Coordinator功能,检查Consumer和Partition情况,进行分配 image.png 这个过程叫rebalance
  • Rebalance

image.png

小结

刚刚总共讲了哪一些可以帮助Kafka提高吞吐或者稳定性的功能?
Producer: 批量发送、数据压缩Broker:顺序写,消息索引,零拷贝Consumer:Rebalance

kafka的缺点

  • 数据复制问题

image.png

  • 重启操作 整个过程下来大概是分钟级别的操作。而公司可能有成千上万台机器,时间成本巨大。(只能一台一台,不能并发) image.png
  • 替换、扩容、缩容

image.png 思考一下替换,扩容,缩容的流程应该是怎样的流程? 同重启。kafka集群针对任何运维操作,只要是节点的变动,都会有复制带来的时间成本问题。

  • 负载不均衡 迁出p3会导致新的数据复制,带来新的IO问题。权衡的负载均衡策略极其复杂。 image.png
  • Kafka问题总结
1.运维成本高
2.对于负载不均衡的场景,解决方案复杂
3.没有自己的缓存,完全依赖PageCache
4.Controller和Coordinator和Broker在同一进程中,大量IO会造成其性能下降

3BMQ

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

3.1架构图

增加proxy层,controlor和coordenator分离,增加分布式数据库。类似数据库读写分离的方案。 image.png

3.2运维操作对比

Proxy和Broker此时都是无状态的概念,不再有复制问题 image.png

3.3HDFS写文件流程(BMQ底层写入)

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

3.4BMQ文件结构

同一个Partition的所偶segement随机打散到不同的DataNode。不会出现大分片需要调整。 image.png

3.5Broker-状态机

保证对于任意分片在同一时刻只能在 1 个Broker上存活。 image.png Recover进行抢锁(利用HDFS的face机制,即一个文件只能由一个进程进行写入)。 Broker可能宕机,recover禁止进行恢复。

  • 写文件流程 image.png
  • 写文件Failover 如果DataNode节点挂了或者是其他原因导致我们写文件失败,应该如何处理? image.png 寻找新的DataNode节点启用

3.6Proxy(代理)

  • 读取流程 image.png wait配置有两个设置,文件大小、时间大小。

3.7多机房部署

对于线上的高可用服务,除了需要防止单机故障还需要防止机房级故障。 image.png 每个机房都可以处理全量的Partition。所有Broker共同承担所有的分片,单个机房出现问题时,进行rebalance。

3.8BMQ高级特性

泳道功能、Databus功能、集群mirror功能、消息索引Parquet功能

image.png

3.9泳道消息

image.png 多人同时测试,需要待上人测试完成 image.png 每多个测试人员,都需要重新搭建个相同配售置的Topic,造成人力和资源的浪费 image.png PPE 的消费者来说,资源没有生产环境多所以无法承受生产环境的流量 image.png 解决主干泳道流量隔离问题以及泳道资源重复创建问题。(Topic只有一个就足够了) image.png

3.10DataBus

原生SDK: image.png 直接使用原生SDK会有什么问题?
1.客户端配置较为复杂2.不支持动态配置,更改配置需要停掉服务3.对于latency不是很敏感的业务,batch效果不佳 Databus:

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

3.11Mirror

思考一下,我们是否可以通过多机房部署的方式,解决跨rigion读写的问题 image.png (读一次在美国的broker要等个半秒不划算)
使用Mirror 通过最终一致的方式,解决跨Region 读写问题。(异步传输)使两地的broker都感觉自己不存在延迟。实际有滞后性,但可以忽略。 image.png

3.12Index

如果希望通过写入的Logld、 Userld或者其他的业务字段进行消息的查询,应该怎么做? image.png 用户需要额外的存储开销,成本高。

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

3.13Parquet

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

  • 行存储与列存储: image.png 直接在BMQ中将数据结构化,通过Parquet Engine,可以使用不同的方式构建Parquet格式文件。这种列式存储文件十分方便大数据进行分析。 image.png

小结

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

消息队列-RocketMQ

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

RocketMQ基本概念

image.png

image.png

RocketMQ-架构

image.png

RocketMQ-存储模型

image.png

RocketMQ-高级特性

  • 事务场景

image.png 两阶段提交机制的处理方式: image.png

  • 延迟发送 提前编辑菜单前一天编辑好定时任务定时发送第二天到点发送接收菜单

image.png

image.png

  • 消费重试和死信队列 当处理失败: image.png 死信队列: image.png

小结

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

总结

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