消息丢失产生的原因
- 对于异步刷盘机制,Broker先将数据写到OS Cache中,在合适的时间OS将OS Cache中的数据刷到磁盘。可能存在刷盘之前,系统宕机,OS Cache数据丢失。
- 即时Broker将数据刷到磁盘了,万一磁盘坏掉,也会丢失消息
- 消费者拉取到一部分消息之后,异步处理消息,主线程响应MQ消息的offset,让MQ以为你处理完了。这时消费者宕机了,异步逻辑还没处理完。因为MQ收到了消费者的offset,MQ就不会进行故障转移(让客户端所在组的其他客户端获取消息)这样也会存在消息丢失。
- 其他
解决方案
1. 同步刷盘:Broker收到生产者的消息后,会将数据写到磁盘后再响应生产者消息写入成功
2. 主从架构:为避免磁盘坏掉导致的数据丢失,可以采用主从架构的模式。即:消息写到Master-Broker之后,Slave-Broker进行同步。当Slave-Broker同步完成,则响应生产者消息写入成功。其实我们部署的Dledger模式,就是这种意思。
3. 客户端手动提交offset,避免消息的异步消费:客户端拉取到一批消息之后,同步处理消息,全部消息处理完成后,在提交offset。这样即使部分消息未处理,客户端宕机了,由于没有提交offset,MQ会自动故障转移到其他客户端
消息零丢失的优劣势
优势:很明显,就是不会丢失消息
劣势:
1. 大大降低MQ的吞吐量:
就同步刷盘而言:消息写入磁盘和写入OS Cache根本不是一个数量级的
就主从架构而言:消息同步到Slave-Broker代价很大
2. 降低消费者的消费能力:
本来可以异步处理消息,为保障零丢失改为同步,消费者消费能力大大降低
零丢失使用场景
对于核心业务,如订单等核心交易系统,绝对不允许消息丢失,此时可以采用零丢失方案。对于非核心业务,消息丢失部分也影响不大,可以考虑异步刷盘和主从架构,既能保证吞吐量,也在一定程度上保障消息不丢失。