[高级消息队列] 消息队列数据丢失和解决办法
数据从生产者除产生,发往MQ,缓存一段时间后再发往消费者。
1.生产者向MQ写数据时出错。
解决方法:
1)使用事务机制,若消息未被成功接收,则会收到异常信息,并可回滚事务和仅需重发。缺点是需要阻塞等待,降低性能。(同步方案)
2)开启confirm模式。所有消息会分配一个唯一ID,当MQ保存后会返回ACK,若出错则会返回NACK。confirm分为普通、批量和异步集中模式。(可以为异步方案)
2.MQ缓存数据时出错(宕机重启等丢失数据)。
解决方法:
开启数据持久化。这样再MQ重启后可以读取并恢复之前的数据。
以RabbitMQ为例,设置持久化的步骤为:
a. 创建queue后将其设置为持久化的。这样会持久化保存queue的元数据。
b. 发送消息时将deliveryMode设置为2,这样queue中保存的消息数据也会被持久化。
对于Kafka,由于Kafka是分布式结构,因此当某个broker宕机时,需要重新选举这些partion的leader。若当follower数据没有完成同步leader就挂了,会导致数据丢失。Kafka的结构使得不需要设置持久化,而需要多个副本保持数据同步。设置如下:
a. 给topic的replication.factor参数设置大于1的值,使得partation至少拥有2个副本。
b. Kafka服务端设置min.insync.replicas参数大于1,使得leader必须至少感知到有一个follower还在联系。也就是说至少还有一份备份。
c. 在生产者端,设置acks=all,要求所有数据写入replica后,才能认为写入成功。
d. 在生产者端,设置retries=MAX,要求一旦写入失败,就无限仅需重试。
3.消费者获取数据后出错(没来得及消费数据,就宕机重启)。
启用ACK机制,以RabbitMQ为例,需要关闭其的自动ACK。消费者处理完消息后向MQ发送ACK,后者再删除消息。
对于Kafka,则是关闭自动提交offset,在处理完消息之后由消费者自行提交offset。