1、ACK两个作用
对于生产者来说 生产者将消息发送到MQ上,MQ会给你一个ack,如果MQ在给你回ACK的时候,突然网断了,ACK没有回给你,但是消息已经到达了MQ上了,此时消息是对消费者可见的,由于你没有收到ack的回复,那么后续的操作会根据业务有所不同,这样就会导致了本地业务处理和消息消费的不一致性性
对于消费者,消费消息之后需要给MQ发送一个ack,告诉MQ已经消费了消息,但是在发给MQack的时候,网断了,ack没有发送成功,但是你以为发送成功了,你进行了后续的操作,实际上MQ没有收到ack,这时候MQ又会重复的给你发送了消息,如果没有做幂等性处理就会有问题
总结一下,ack是:生产者-mq服务器、mq服务器-消费者,三者之间的关系,针对没有收到ack的,前者会重复发送
2、本地消息表两个作用
本地消息表 会记录生产者是否发送失败和消费者是否消费成功
而本地消息表是,起到,生产者是否发送消息成功、消费者是否消费成功,不成功则跑补偿
3、事务消息
本地消息表 是因为rabbitmq没有事务消息 所有需要用到本地消息表,在rocketMQ中存在事务消息,人工只处理那些消费失败的消息
就是 生成者给MQ先发一条消息 消息状态是unknown状态,此时对消费者这条消息是不可见的,发送成功之后MQ会给生产者一个ack,这时候生产者会进行数据库的操作,如果操作数据库失败会进行回滚只需要向mq 回一个rollback将unknown状态的消息删除就行,如果操作数据库成功会回一个commit的ack告诉mq将unknown的消息改为正常的消息,此时消息对消费者可见,也就可以正常消费
这就是三段式的ack rabbitMQ是不支持这种事务消息的
也许你会问,如果最后一次给MQ发送rollback或者commit的时候网断了,mq没有收到最后一次ack,但是数据库事务已经提交了,消息还是unknown状态会怎么样?
这一点rocketMQ已经给你做好了,每隔5s mq会回查那些unknown状态的消息,回调我们的方法,在回调方法里面可以将消息重新发送
这就是消息的补偿,这就是为什么rocketMQ不需要做本地消息表的原因之一
4、消息持久化
(1)、队列持久化,通过参数durable=true实现。
(2)、消息持久化,通过参数deliveryMode=2实现,deliveryMode=1代表不持久化。
(3)、交换机exchange持久化,通过参数durable=true实现。
5、如何正确消费一条消息
先说一下 ACK机制 然后说一下MQ的持久化机制,最后说一下本地消息表
要想保证消息的100%不丢 其实就是MQ保证了99.9%,剩下的0.1%需要人工差错
再说一下人工差错的步骤与方法
对于消费失败的我们都是记录日志的,并且发送邮件通知我们,然后我们有个后台管理系统,将日志里面的消息的信息手动再发一遍,也可以批量的发送
网友评论