用了上面提到的事务消息机制,可以保证消息已经进入到MQ的存储层了,可以被下游消费者系统看到。此时可能下游消费者系统还没来得及获取这条消息,然后恰巧在此时,你的这条消息仅仅停留在os cache中,还没进入到ConsumeQueue磁盘文件里,然后此时这台机器突然宕机了,os cache中的数据全部丢失,此时必然导致你的消息丢失了。
就算我们很走运,比如你的消息已经进入了Topic的ConsumeQueue磁盘文件了,那就一定不会丢失了吗?
也是未必的,即使消息进入了磁盘文件,但是这个时候下游消费者还没来得及消费这条消息,然后这台机器的磁盘突然坏了,一样会导致这条消息丢失。
所以我们需要明确一个前提,无论是通过比较简单的同步发送消息+反复多次重试的方案,还是事务消息的方案,哪怕我们确保消息已经写入MQ成功了,此时也未必消息就不会丢失了。
异步刷盘 vs 同步刷盘
到底要怎么去确保消息写入MQ之后,MQ自己不要随便丢失数据呢?
解决这个问题的第一个关键点,就是将异步刷盘调整为同步刷盘,所谓异步刷盘就是消息即使写入MQ,他也就在机器的os cache中,没有进入磁盘,要过一会儿等操作系统自己把os cache里的数据实际刷入磁盘文件中去。
所以在异步刷盘的模式下,我们的写入消息的吞吐量是极高的,毕竟只要进入了os cache这个内存就可以了,写消息得到性能就是写内存的性能,但是这种情况下,可能会导致数据的丢失。
所以如果一定要确保数据零丢失的话,可以调整MQ的刷盘策略,需要调整broker的配置文件,将其中的flushDiskTyp