rocketMq
1、rocketMq延迟消息实现:
1) producer要将一个延迟消息发送到某个Topic中
2) Broker判断这是一个延迟消息后,将其存到SCHEDULE_TOPIC_XXXX中,延迟消息有18个延迟级别,所以SCHEDULE_TOPIC_XXXX中有18个队列
3) Broker内部通过一个延迟服务(delay service)检查消息是否到期,每一个延迟级别即每一个queue都会有一个单独的定时器,定时器首先检查队列中尚未投递的第一条消息。
4) 检查消息时,从消息tagsCode中解析出消息应当被投递的时间,与当前时间做比较,判断是否应该进行投递,如果若到达了投递时间,则构建一个新的消息,投递到目标topic中。
5) 消费者消费目标topic中的延迟投递的消息
2、rocketMq事务消息流程:
比如生产者要完成一个A操作,消费者要完成一个B操作。事务消息要保证生产者和消费者的AB操作原子性,即都成功或者都不成功。
a、账户服务作为 Producer 向 Broker 发送一条 half 消息。
b、half 消息发送成功后,执行本地事务,执行成功则向 Broker 发送 commit 请求,否则发送 rollback 请求。
c、如果 Broker 收到的是 rollback 请求,则删除保存的 half 消息。
d、如果 Broker 收到的是 commit 请求,则保存扣减库存消息(这里的处理是把消息从 half 队列投递到真实的队列),然后删除保存的 half 消息。
e、如果 Broker 没有收到请求,则会发送请求到 Producer 查询本地事务状态,然后根据 Producer 返回的本地状态做 commit/rollback 相关处理。
3、rocketMq死信队列和重试队列
当一条消息初次消费失败,消息队列MQ会自动进行消息重试;达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息,此时,消息队列MQ不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中,这种无法被消费的消息称为死信消息(Dead-Letter Message),存储死信消息的特殊队列称为死信队列(Dead-Letter Queue)
重试队列,具体指消费端消费消息失败时,为防止消息无故丢失而重新将消息回滚到Broker中。重试队列一般分成多个重试等级,每个重试等级一般也会设置重新投递延时,重试次数越多投递延时就越大。举个例子:消息第一次消费失败入重试队列Q1,Q1的重新投递延迟为5s,在5s过后重新投递该消息;如果消息再次消费失败则入重试队列Q2,Q2的重新投递延迟为10s,在10s过后再次投递该消息。以此类推,重试越多次重新投递的时间就越久,为此需要设置一个上限,超过投递次数就入死信队列
4、rocketMq防消息丢失
producer:利用同步发送等待返回值+重试机制(即producer没收到broker的ack,需要重试),尽可能减小消息丢失的可能性。和kafka类似
broker:Broker通常采用一主(master)多从(slave)部署方式。为了保证消息不丢失,消息还需要复制到slave节点。默认方式下,消息写入master成功,就可以返回确认响应给生产者,接着会异步把消息复制到slave节点,为了进一步提高消息的可靠性,我们可以采用同步的复制方式,master 节点将会同步等待slave节点复制完成,才会返回确认响应,且使用同步刷盘的方式,防止异步刷盘导致的消息可能丢失。(rocketmq支持broker同步和异步刷盘)
consumer:Consumer先pull消息到本地,消费完成后,才向broker返回ack。如果Broker未收到消费确认响应或收到其他状态,消费者下次还会再次拉取到该条消息