要保证消息的可靠性,先来思考一下从哪些方面保证呢?
这要看消息的生命周期,既然保证可靠性,那么就是要保证 A 发送给 B 的消息一定可以成功,那么首先要保证发送成功,其次要保证 B 接收成功,而在 RocketMQ 中,消息是先发送到 Broker 中了,那么还需要保证 MQ 在 Broker 中不会丢失,因此 RocketMQ 是从三方面保障了消息的可靠性:生产者、Broker、消费者
生产者保证消息的可靠性:生产者发送消息分为同步发送、异步发送、单向发送三种方式,那么单向发送是没有消息可靠性的保证的,而在同步和异步发送中,都可以通过添加消息的重试次数
、添加 ResponseCode
、添加当前 Broker 不可用时发送到其他 Broker
三种策略来保证数据的 发送可靠性
Broker 保证消息的可靠性:即保证消息发送到 Broker 中,不会因为 Broker 突然宕机而导致数据丢失,那么其实就是保证消息存储在 Broker 的可靠性,肯定是需要将数据存储在磁盘上才可靠,那么数据存储到磁盘上的方式还分为了 同步刷盘
和 异步刷盘
,同步刷盘不会丢失消息,异步刷盘可能会丢失!
那么 Broker 可能磁盘还会损坏呢,因此还需要通过备份节点来保证消息的可靠性,因此呢在 Broker 端有两种可靠性保证:刷盘策略(同步刷盘、异步刷盘)
和 备份节点
消费者保证消息的可靠性:保证数据的消费,通过先消费数据,再提交成功状态来保证,消费者还需要具有一定的 幂等性
处理,因为消费者可能会消费多条消息
如果消费者最终重试消费消息失败,那么还可以通过去死信队列中消费数据来保底
还是从三个方面来保证:发送端、存储端、消费端
发送端保证消息的有序性:要保证有序性,那么必须要将需要保证有序性的消费给放到同一个队列中才可以,因此在 Topic 中设置一个队列就可以保证消息的有序性;如果在 Topic 中设置了多个队列,那么只需要将需要保证有序的消息放在同一个队列中即可,这种方式需要使用下图中的 api 来实现一个队列选择器,让有序消息选择同一个队列发送即可
存储端保证消息的有序性:通过 CommitLog + MessageQueue + IndexFile 来保证消息在 MessageQueue 中有序存储即可
消费端保证消息的有序性:可以为消费者注册有序消费的监听器即可 MessageListenerOrderly
如果想要保证在多个队列中消息的有序性,可以使用
全局的时间戳
,在消费端记录已经消费消息的最小时间戳
即可保证消费的有序性!