即使消息已经进入磁盘文件了,但是这个时候消费者系统还没来得及消费这条消息,然后此时这台机器的磁盘突然就坏了,就会一样导致消息丢失,而且可能消息再也找不回来了,同样会丢失数据。
明确一个前提:保证消息写入MQ不代表不丢失
因为即使你写入MQ成功了,这条消息也大概率是仅仅停留在MQ机器的os cache中,一旦机器宕机内存里的数据都会丢失,或者哪怕消息已经进入了MQ机器的磁盘文件里,但是磁盘一旦坏了,消息也会丢失。如果消息丢失了,你的消费者系统还没来得及消费,那么他就永远没机会消费了,所以对于你而言,如果你仅仅只是使用MQ的话,可能不清楚MQ集群内部发生过的一些机器故障,也就不清楚数据丢失的具体原因了。同步刷盘VS异步刷盘
解决这个问题的第一个关键点,就是将异步刷盘调整为同步刷盘。
所谓的异步刷盘,就是之前我们一直说的那种模式。也就是说,你的消息即使成功写入了MQ,他也就在机器的os cache中,没有进入磁盘里,要过一会儿等操作系统自己把os cache里的数据实际刷入磁盘文件中去。所以在异步刷盘的模式下,我们的写入消息的吞吐量肯定是极高的,毕竟消息只要进入os cache这个内存就可以了,写消息的性能就是写内存的性能,那每秒钟可以写入的消息数量肯定更多了,但是这个情况下,可能就会导致数据的丢失。
所以如果一定要确保数据零丢失的话,可以调整MQ的刷盘策略,我们需要调整broker的配置文件,将其中的flushDiskType配置设置为:SYNC_FLUSH,默认他的值是ASYNC_FLUSH,即默认是异步刷盘的。如果调整为同步刷盘之后,我们写入MQ的每条消息,只要MQ告诉我们写入成功了,那么他们就是已经进入了磁盘文件了!比如我们发送half消息的时候,只要MQ返回响应是half消息发送成功了,那么就说明消息已经进入磁盘文件了,不会停留在os cache里。通过主从架构模式避免磁盘故障导致的数据丢失
我们必须要对Broker使用主从架构的模式,也就是说,必须让一个Master Broker有一个Slave Broker去同步他的数据,而且你一条消息写入成功,必须是让Slave Broker也写入成功,保证数据有多个副本的冗余。这样一来,你一条消息但凡写入成功了,此时主从两个Broker上都有这条数据了,此时如果你的Master Broker的磁盘坏了,但是Slave Broker上至少还是有数据的,数据是不会因为磁盘故障而丢失的。
对于主从同步的架构,是基于DLedger技术和Raft协议的主从同步架构,如果采用了这套架构,对于所有的消息写入,只要写入成功,那就一定会通过Raft协议同步给其他的Broker机器。此时任何一台机器的磁盘故障,数据也是不会丢失的。
