这是我参与【第五届青训营】伴学笔记创作活动的第11天
消息队列
案例一:系统崩溃
如果此时记录存储程序所在的机房被删库跑路了,上面这个流程会发生什么问题?
解决方案:解耦
案例二:服务能力有限
面对庞大的请求量,处理订单的服务只能同时处理10订单请求
解决方案:削峰
案例三:链路耗时长尾
对于这个流程应该怎么优化来挽回用户?
解决方案:异步
案例四:日志存储
什么是消息队列?
消息队列(MQ),指保存消息的一个容器,本质是一个队列。但这个队列,需要支持高吞吐、高并发,并且高可用。
业界消息队列对比
- Kafka:分布式的、分区的、多副本的日志提交服务,在高吞吐场景下发挥比较出色
- RocketMQ:低延迟、强一致、高性能、高可靠、万亿级容量和灵活的可扩展性,在一些实时场景中运用较广
- Pulsar:下一代云原生分布式消息流平台 ,集消息、存储、轻量化函数式计算为一体、采用存算分离的架构设计
- BMQ:和Pulsar架构类似,存算分离,初期定位是承接高吞吐的离线业务场景,逐步替换掉对于的Kafka集群
Kafka
使用场景
- 搜索服务
- 直播服务
- 订单服务
- 支付服务
如何使用Kafka
- 创建集群
- 新增Topic
- 编写生产者逻辑
- 编写消费者逻辑
基本概念
- Topic:逻辑队列,不同Topic可以建立不同的Topic
- Cluster:物理集群,每个集群可以建立多个不同的Topic
- Producer:生产者,负责将业务消息发送到topic中
- Consumer:消费者,负责消费Topic中的信息
- ConsumerGroup:消费者组,不同组Consumer消费进度互不干涉
Offset
消息在 partition 内的相对位置信息,可以理解为唯一ID,在 partition 内部严格递增
Replica
每个分片有多个 Replica,Leader Replica 将会从 ISR 中选出
数据复制
Kafka架构
Zookeeper:负责存储集群元信息,包括分区分配信息等
Producer-数据发送
使用批量发送可以减少io次数,加强发送能力
思考:如果消息量很大,网络带宽不够用,如何解决?
Producer-数据压缩
通过压缩,减少消息大小,目前支持Snappy、Gzip、LZ4、ZSTD压缩算法
Broker-数据的存储
如何存储到磁盘?
Broker-消息文件结构
数据路径:/Topic/Partition/Segment/(log | index | timeindex | ...)
Broker-磁盘结构
移动磁头找到对应磁道,磁盘转动,找到对应扇区,最后写入。寻道成本比较高,因此顺序写可以减少寻道所带来的时间成本。
Broker-顺序写
采用顺序写的方式进行写入,以提高写入效率
如何找到消息
Consumer 通过发送 FetchRequest 请求消息数据,Broker 会将指定 Offset 处的消息,按照时间窗口和消息大小窗口发送 Consumer,寻找数据这个细节是如何做到的呢?
偏移量索引文件
目标:寻找 offset = 28
二分找到小于目标 offset 的最大索引位置
时间戳索引文件
二分找到小于目标时间戳最大的索引位置,再通过寻找 offset 的方式找到最终数据。
Consumer-消息的接收端
如何解决 Partition 在 Consumer Group 中分配的问题?
Low Level
通过手动进行分配,哪一个 Consumer 消费哪一个 Partition 完全由业务来决定。
缺点
- 没有容灾机制,当某个Consumer挂掉的时候,消息得不到及时的处理。
- 数据中断的问题,新增消费者的时候,需要停止消费
High Level
它自动管理每个Topic的每个Partition的offest,将从某个Partition读取的最后一条消息的offest存于Zookeeper中
总结
消息队列在大型电子商务类网站,如京东,淘宝等都有着深入的应用,消息队列的主要租用是消除高并发访问高峰,加快网站的响应速度,。常用于步处理,流量削峰,应用解耦和消息通讯等四个场景。