消息队列学习笔记(Kafka,RocketMQ)

215 阅读5分钟

1. 消息队列有什么用?

生产者和消费者的速度和稳定性不一致的时候,需要消息队列作为抽象层,弥补双方之间的差异。使用消息队列时,生产者把消息往消息队列里就可以马上得到响应,无需再等待处理结果。消息队列主要是为了消除高并发访问高峰,加快网站的响应速度。

2. 消息队列Ksfka

Producer:消息生产者,负责把产生的消息发送到Kafka服务器上。

Consumer:消息消费者,从Kafka服务器读取消息。

Consumer Group:消费者群组,每个消息消费者可以划分为一个特定的群组。

Topic:这是Kafka使用中非常重要的一个术语,它相当于消息的"身份标识",消息生产者产生消息时会给它贴上一个Topic标签,当消息消费者需要读取消息时,可以根据这个Topic读取特定的数据。

Broker:Kafka集群中包含的服务器。

2.1 ISR机制

image.png

每个partition都做了数据同步,有数据副本,保证了生产者发来消息的可靠性。Leader用来对外写入和消费,Follower不断从Leader拉去数据,保持同步。ISR机制Follower与Leader之间有差距,如果差距过大就会被踢出Partition。消息丢失问题怎么解决?

acks=-1是保证消息从生产者到broker不丢失的最佳设置方式;broker到磁盘丢消息,最好的方案还是设置多副本,一个分区设置几个副本,当broker故障的时候,如果还有其他副本,那么数据就不会丢失。

2.2 Producer到Broker

批量发送可以提高消息量,减少IO次数,加强发送能力。

若网络带宽不足,可以通过压缩可以减少消息大小,压缩算法有Snappy、Gzip等。

2.3 Broker到磁盘的数据存储

2.4 Broker采用顺序写的方式进行写入

通过发送FetchRequest请求消息数据,通过二分法找到小于目标offset的最大文件。

2.5 Broker零拷贝

将数据在内核空间直接从磁盘文件复制到网卡中,而不需要经由用户态的应用程序之手

3. 消息队列 BMQ

BMQ兼容Kafka。实际上对于BMQ来说,所有节点变更的操作,都仅仅只是集群元数据的变化,通常情况下都能秒级完成,而真正的数据已移到下层分布式文件存储去了,所以运维操作不需要额外关心数据复制带来的时间成本。

多了一个proxy来承担Controller的功能

image.png

4. RockerMQ

4.1 与Kafka的对比:

= image.png

4.2 与Kafka的不同之处:

RockerMQ可以分为Producter,Consumer,Broker三个部分,Kafka中Partitonion概念在此被称为ConsumerQueue。

RockerMQ的存储模型不同,ConsumerQueue存储的不是真实的数据,而这个Queue所有消息在CommitLog上的位置,真实数据只存在在CommitLog。

image.png

4.3 高级特性:事物消息

  1. 分布式事务有很多种解决方案,其中一种就是使用RocketMQ的事务消息来达到最终一致性。
  2. 生产者向RocketMQ服务端发送半消息,什么叫半消息呢,就是暂不能投递消费者的消息,发送方已经将消息成功发送到了MQ服务端,此时消息被标记为暂不能投递状态,需要等待生产者对该消息的二次确认。
  3. MQ服务端给生产者发送ack,告诉生产者半消息已经成功收到了。
  4. 发送方开始执行本地数据库事务的逻辑。
  5. 执行完成以后将结果告诉MQ服务端,本地事务执行成功就告诉commint,MQ Server收到commit后则将半消息状态置为可投递,consumer最终将收到该消息;本地事务执行失败则发送rollback,MQ Server收到rollback以后则删除半消息,订阅费将不会收到该条消息。
  6. 未收到第4步的确认信息时,回查事务状态。消息回查: 因为网络闪断、生产者重启等原因,RocketMQ 的发送方会提供一个反查事务状态接口,如果一段时间内半消息没有收到任何操作请求,那么 Broker 会通过反查接口得知发送方事务是否执行成功。
  7. 发送方收到消息回查后,需要检查对应消息的本地事务执行的最终结果。
  8. 发送方根据检查本地事务的最终状态再次提交二次确认,发送commit或者rollback。上述就是整个事务消息的执行流程,下面我们来看下如何在代码中操作。
  9. RocketMQ中提供了一个TransactionListener接口,我们需要实现它,然后在executeLocalTransaction方法中实现执行本地事务逻辑。

4.4 高级特性:延迟消息

在一段时间之后,完成一个工作任务的需求,例如:滴滴打车订单完成之后,如果用户一直不评价,48小时会将自动评价为5星;外卖下单30分钟不支付自动取消等等。这种问题的解决方案有很多种,其中一种就是用RocketMQ的延迟队列来实现。