这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记。
前言
- 系统崩溃
- 服务处理能力有限
- 链路耗时长尾
- 日志如何处理
1. 系统崩溃
解决方案:解耦。 消息队列 !
用消息队列在存储服务前收发消息,存储服务从消息队列里获取请求。储存服务崩溃,消息队列还能够收发消息,不会影响业务。
2. 服务处理能力有限
解决方案:削峰。 消息队列 !
先将大量请求存在消息队列中,每次从消息队列获取少量请求进行处理。
3. 链路耗时长尾
解决方案:异步。消息队列 !
4. 日志如何处理
解决方:先存入消息队列里。再进行处理
什么是消息队列
保存消息的一个容器。支持高吞吐,高并发,高可用。
目录
- 前世今生
- 消息队列-Kafka
- 消息队列-BMQ
- 消息队列-RocketMQ
前世今生
诞生于1985年,TIB。
1993年,IBM MQ / WebSphere。
1997年,MSMQ。
2001年,JMS,Java API。
2004年,Rabbit MQ,规范,高级协议。
2010年,Kafka ,linked开源。
2011年,RocketMQ,阿里自研。
2012年,Pilsar,Yahoo。
对比
Kafka:高吞吐
Rocket MQ低延迟,强一致,高性能,高可靠,灵活可扩展。
Pulsar: 存算分离
BMQ:存算分离,初期承接高吞吐的离线业务场景。
Kafka
1. 使用场景
日志信息,Metrics数据,用户行为。
2. 如何使用
创建集群 -> 新增 Topic -> 编写生产者逻辑 -> 编写消费者逻辑
3. 基本概念
- Topic:逻辑队列,不同业务逻辑可以建立不同的 Topic
- Cluster:物理集群,每个集群中可以新建不同的 Topic 处理不同的业务逻辑
- Producer:生产者,服务将业务消息发送到 Topic中
- Consumer:消费者,负责消费 Topic 中的消息
- ConsumerGroup:消费者组,不同组的 Consumer 消费进度互不影响
Topic 分区,消息并发处理,提高单个Topic处理能力。
Offset:消息再 partition 内的小队位置信息,可以理解为唯一ID,在 partition 内部严格递增。
Replica:每个分片有多个 Replica,Leader Replica 将会从 ISR 中选出。
Follower从Leader中拉取数据,差距过大提出 ISR 。Leader如果宕机,从Follower里面选出一个当Leader。
4. 数据复制
Controller控制Broker上的分配.
5. Kafka架构
ZooKeeper和Controller配合。Controller计算好的方案都会放在这个地方。
6. 一条消息的自述
从 Producer -> Broker -> Consumer
如果对于 Producer 如果发送一条消息等待成功后再发送下一条,处理能力太小。
支持批量处理,加强发送能力。如果单个大小很大,消息量很大,带宽不够用怎么办。
通过压缩,减小消息大小,支持Snappy,Gzip,LZ4,ZSTD压缩算法。默认Snappy,ZSTD比较好。
现在 Producer 将压缩好的消息发送到了Broker。
Broker信息文件结构:
Broker 将文件存入磁盘中,寻道成本高。通过顺序写来提高效率,尽量不移动磁头。
Consumer 向 Broker 请求消息,Broker 如何寻找数据。
根据 offset 来寻找,二分查找小于目标 offset 的最大文件。
找到文件之后,文件结构如下:
再二分查找小于目标的最大Batch,然后在Batch中顺序查找。
通过时间戳来查找的话,先通过时间戳来找到对应的offset。再通过offset查找。
数据从磁盘到消费者进程,零拷贝:
Consumer 收到从 Broker 发送的数据之后,Partition如何在ConsumerGroup中分配。
-
手动分配:手动分配哪一个Consumer消费哪一个Partition。
不能自动容灾,扩展机器会导致服务停止。优点是比较快。
-
自动分配:
Rebalance
总结
Producer: 批量发送,数据压缩
Broker:顺序写,消息索引,零拷贝
Consumer:Rebalance
问题: - 运维成本高 - 对于负载不均衡的场景,解决方案复杂 - 没有自己的缓存 - controller 和 coordinator 和 broker 在同一进程,大量 IO 会造成性能下降。
这些问题应该怎么解决呢。下节分享。