MQ如何保证消息不丢失
- 问题分析
- 具体分析及解决方案
- RabbitMQ
- 生产者
- RabbitMQ配置
- 消费者
- Kafka
- Kafka配置
- 消费者
问题分析
从Kafka和RabbitMQ进行分析,MQ消息丢失的情况有生产者推送消息时数据丢失,MQ中间件宕机情况下数据丢失,消费者消费时消息丢失。
- 问题延伸:如何保证MQ消息的顺序性,如何保证不重复消费
具体分析及解决方案
RabbitMQ的情况下,消息不存在queue里面,queue的数据时存在内存当中的,不一定会被持久化,当中间件重启后,数据会丢失。消费者默认自动是ack确认机制,不关注数据是否持久化完成。
RabbitMQ
生产者
- 可以使用其自带的事务机制,在生产者在推送数据时开启事务,但是这是串行化执行,会影响其他事务的执行;
channel.txSelect
try{
}
catch(){channel.rollback
}
channel.commit
- 可以使用comfirm机制,当消息被RabbitMQ接收了,会给生产者发送ask,否则发送回调noack方法。保证消息不丢失,也保证了生产者的高效性。异步执行
RabbitMQ配置
对于经典队列,将durable属性设置为true,开启queue队列的持久化
对于消息的持久化,保证RabbitMQ在收到消息及时落盘,发送消息时将deliveryMode属性设置为2
设置完后,在RabbitMQ重启后,会恢复Queue里面和Message消息
消费者
关闭自动提交ack机制,在消费者消费完成后手动提交ack
Kafka
Kafka配置
- 这种情况下必须保证每个分区都要有两个副本存在。设置replication.factor大于1
- 设置min.insync.replicas大于1,保证每个leader必须有一个follower跟自己保持联系
- 将akcs设置为all,即acks=all,要求每条数据必须写入所有replica,及写入到所有的副本,在leader挂了之后follower通过选举之后成为新的leader可以它的数据可以被消费。
消费者
关闭自动提交offset机制,手动提交offset