如何保证消息可靠性

一、分布式解决方案

1.1 柔性事务-可靠消息+最终一致性方案(异步确保型)

实现:业务处理服务在业务事务提交之前,向实时消息服务请求发送消息,实时消息服务只记录消息数据,而不是真正的发送。业务处理服务在业务事务提交之后,向实时消息服务确认发送。只有在得到确认发送指令后,实时消息服务才会真正发送。

依次达到最终一致性目的,而且,可以承受大的并发量。

但是,这些的前提,都要保证消息的可靠性。那我们究竟如何保证消息可靠性?

二、如何保证消息可靠性-消息丢失

2.1 消息发送出去,由于网络问题没有抵达服务器

1.做好容错方法(try-catch),发送消息可能会网络失败,失败后要有重试机制,可记录到数据库,采用定期扫描重发的方式

2.做好日志记录,每个消息状态是否都被服务器收到都应该记录

3.做好定期重发,如果消息没有发送成功,定期去数据库扫描未成功的消息进行重发

2.2 消息抵达Broker(代理),Broker要将消息写入磁盘(持久化)才算成功。此时Broker尚未持久化完成,宕机。

1.publisher也必须加入确认回调机制,确认成功的消息,修改数据库消息状态。

保证消息不丢失,可靠抵达,可以使用事务消息,性能下降250倍,为此引入确认机制

publisher confirmCallback 确认模式

publisher returnCallback 未投递到queue退回模式

consumer ack机制

我们消息的生产者,把消息只要发给Broker,消息代理(Broker)收到消息以后,相当于服务器收到了。

但是,只有服务器,通过交换机把这个消息,抵达送给队列以后,才算这个消息完整的持久化保存到队列里面。

所以,我们就可以使用生产者的确认模式,只要消息存到队列里面了,那么就可以放心了,这个队列里面就有消息了,就等着消费了。

2.3 自动ACK的状态下。消费者收到消息,但没来得及消费,然后宕机

1.一定开启手动ACK,消费成功才移除,失败或者没来得及处理就noAck并重新入队

生产者发送一个消息,确认已达,已经抵达了我们服务器Broker

而我们消费者,在这消费消息,它呢刚把消息拿到,还没来得及消费,它给宕机了,宕机以后,如果是自动ACK的状态,会自动回复服务器,我已经收到了,但是,我却没有消费成功,那这个消息相当于走了一遍过场,什么都没做,就从队列里删掉了。

所以为了预防这种情况,一定要开启手动ACK的模式,只有消费者确认把这个消息消费成功以后,才告诉服务器,你给我删掉,否则只要给服务器一回复ACK,这个消息就被它删掉了,删掉以后就再也没有这个消息了。

2.4 总结

综上,为了防止消息丢失,我们需要保证好以上三点。

1.做好消息确认机制(publisher, consumer【手动ACK】)两端确认

2.每一个发送的消息都在数据库做好记录定期将失败的消息再次发送一遍

三、如何保证消息可靠性-消息重复

3.1 消息重复

1.消息消费成功,事务已经提交,ack时,机器宕机。导致没有ack成功,Broker的消息重新由unack变为ready,并发送给其他消费者。

监听器收到消息以后,会调用业务逻辑处理,假设,现在消息消费成功了,事务逻辑也处理完了,这个方法只要一调,我们service整个事务完成,它就提交了。

但是,提交了以后,接下来正好走到划线处,准备手动ACK时,服务宕机了,代码的下面不走了,相当于我们没有给mq broker回复成功消费。

然后,消费者就跟它断开连接了,一断开连接,我们的mq就认为没有处理成功,因为我们是手动ACK模式,然后,消息相当于从unacked状态,变成ready状态,重新处理,变成ready状态,它又会发给其他的消费者。

其他消费者收到以后,再调一次方法,相当于同样的消息收到了两遍。

2. 消息消费失败,由于重试机制,自动又将消息发送出去

3.成功消费,ack时宕机,消息由unack变为ready,Broker又重新发送

1)消费者的业务消息接口应该设计为幂等性的。比如扣库存有工作单的状态标志

幂等的,想要解锁库存,先判断库存状态为没解锁的,才能进行解锁

解锁后,我们还会修改库存状态,为已解锁

只要我们解锁一遍,你第二遍再来解锁,这个已经解锁了,就不会再解锁了。

2)使用防重表(redis/mysql),发送消息每一个都有业务的唯一标识,处理过就不用处理

每一个消息由于都有一个唯一id,只要它被处理过了,我们可以在这个防重表里记录一下,它已经被处理过了,那第二次来就不处理了。

3)rabbitMQ的每一个消息都有redelivered字段,可以获取是否是被重新投递过来的,而不是第一次投递过来的

四、如何保证消息可靠性-消息积压

生产者会生产消息给我们的消息队列,消费者会监听队列消费消息,但是,消息队列里的消息太多,肯定会影响一些性能,所以,消息积压会带来mq的性能下降,所以,一定要解决消息积压的问题。

消息在哪些情况下会积压?

1. 消费者宕机积压

mq没有连上任何一个消费者,或者消费者太少了,没有人去消费消息队列里面的消息,而且,生产者还源源不断的生产消息,那就会导致消息积压,

2.消费者消费能力不足积压

宕机就类似于能力不足,本来有10个消费者,然后,挂了9台,就剩一台,最终导致消息积压

3.发送者发送流量太大

上线更多的消费者,进行正常消费

上线专门的队列消费服务,将消息先批量取出来,记录数据库,离线慢慢处理。

视频教程

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值