这是我参与「第五届青训营」伴学笔记创作活动的第11天。青训营的第十三次课程中对消息队列应用场景,以及三种流行的消息队列进行了讲解,下面是我对本次课程内容的一些总结。
消息队列应用场景
- 解耦:系统的一些记录可以发送至消息队列,以防止当外部系统崩溃时的系统阻塞;
- 削峰:将大规模的请求可以放入消息队列,以防止系统被流量打爆;
- 异步:将请求发送至消息队列,可以使得请求异步的并发被执行;
- 日志:消息队列可以自动将请求的日志进行保存,用于系统日志记录;
Kafka基本原理
Kafka消息队列的使用流程为:(1)创建Topic(即特定的业务逻辑);(2)编写消费者和生产者的业务逻辑;
其中,每个Topic由多个Partition组成,其目的是为了提高数据的容错性。对于一条数据记录(包含在一定的数据分区中),其副本存在于多个Partiton中。
对于Producer向消息队列发送请求的过程中,其使用批量提交的方式减小IO请求数量,并使用压缩的方法减小请求消息大小;
对于一个Partition中的数据,其以日志的形式写入到磁盘中。其中每个日志段包含实际日志文件、偏移量索引文件(用于加速查找)、时间戳索引文件(用于判断日志是否过期)。
在写入过程中,Kafka通过顺序写日志的方法提高写入效率;在读取过程中,Kafka通过寻找特定偏移量的方法访问记录。当拿到一个偏移量时,首先通过偏移量索引文件的文件名找到大于该偏移量的索引文件,并在索引文件中进行二分查找,以找到特定日志记录在日志文件中的位置。
并且,为了优化数据拷贝的性能,Kafka使用了内存直写socket缓存的方式提高效率。
对于Comsumer,其从Topic中获得请求并执行。其中,请求到Comsumer的具体负载均衡平衡规则如下:
- 在一个消费组间,其需要找到负载最小的Broker(即一个Topic中的服务器),并达成共识,使得该Broker称为协调者;
- 消费者向协调者发送加入请求,其中首个加入的称为领导者;
- 领导者提供具体的负载均衡策略,并发送至协调者,其他消费者遵循该负载均衡策略;
- 消费者需要定期向协调者发送心跳信息,以声明自身是存活的。
BMQ基本原理
BMQ旨在于解决Kafka框架中存在的一些问题:
- 升级效率差:当程序进行升级时,分区的Leader需要关闭重启,此时Leader由其他的服务器所担任。此时新Leader仍然在接收请求,旧Leader在重启后需要在跟上新Leader时才能完成同步并重新作为Leader。而且,该行为是不可并行的,导致更新时间效率差;
- 负载不均衡:不同分区间存储的数据量级可能是相差较多的,造成数据负载的不均衡,对其解决方法困难。
- Kafka中仅依赖操作系统的内存缓存,没有自己的缓存;
在BMQ中,数据由分布式存储系统所存储,其粒度是以记录而非分区为单位的,从而解决了负载不均衡的问题。并且,由于Broker是无状态的,对于程序升级过程中仅需对Proxy的负载均衡策略进行修改即可完成系统升级。
在写入过程中,数据将被存储在内存缓存中,并被异步的写入至持久化存储中,该操作使得写入的吞吐量增加;在读取过程中,将优先从内存缓存中读取。
并且,在BMQ系统中,每个Partition被分配在不同的机房中,以防止机房级别的故障使得系统不可用。
RocketMQ基本原理
RocketMQ的主要应用场景为低延迟的场景,对于吞吐量高的场景则不太友好。
在RocketMQ中,Broker的概念是基于机器的,相比Kafka的粒度更大一些。
当生产者发送消息时,被记录在统一的Commitlog中,CommitLog通过解析信息将消息的索引发送到不同的消费者对列中,由不同的消费者所消费。