1.发送者的可靠性
1.1生产者重连
有时由于网络波动等原因,发送方一次可能没有连接上RabbitMQ,我们可以配置发送方的连接失败重试机制。但需要注意的是:SpringAMQP提供的重试机制是阻塞式的重试,也就是说多次重试等待的过程中,当前线程是被阻塞的,会影响业务性能。
1.2生产者确认机制
当业务场景对消息的可靠性要求较高时,可以开启消息确认机制,就是当生产者将消息发送出去后,通过回调函数来判断消息是否发送成功,但是此举会导致效率降低,谨慎使用。
1.改动application.yml配置文件
2.添加配置文件(投递成功但路由失败的回调)
3.发送消息处
2.MQ的可靠性
2.1Lazy Queue
懒惰队列,消息数据都需要持久化到硬盘,消费时再去硬盘中取。开启持久化和生产者确认时,RabbitMQ只有在消息持久化完成后才会给生产者返回ACK回执。
3.消费者可靠性
3.1消息确认机制
我们可以把消费者的消息确认模式改为auto,这样当消费者从队列中获取消息执行时,可以返回消息的执行状态。如果出现异常,那么队列中消息不会删除,消息会不断的重新入队到队列,再重新发送给消费者,无限循环....
3.2失败重试机制
出现异常后,我们不能让其一直循环下去,这样会影响整体性能,可以考虑设置失败重试机制,就是再重试多少次之后就应当停止:
但是问题又来了,停止之后消息怎么处理呢,有三种策略:丢弃、依旧放入队列、给专门存放异常消息的交换机。
3.3业务幂等性
幂等是一个数学概念,在程序开发中,则是指同一个业务,执行一次或多次对业务状态影响是一致的。
3.3.1面试问题:表单重复提交的解决思路?
-
前端拦截:在前端设置一个变量标志位,当表单提交成功后,将该标志位设置为true,并在后续提交时进行检查。如果标志位为true,则阻止表单的再次提交。
-
后端拦截:我的思路就是前端发的提交表单请求是携带token的,那么后端在拦截器中验证token无误后,在Redis中查询是否有用户userid的token键值,没有的话可以使用setnx在Redis中存储token信息并且设置一个较短的过期时间,如果设置失败或者已经存在,则予以不处理。
3.3.2消息幂等性
给每个消息生成唯一的标识ID,利用消息转换器来实现:
具体的实现方案:每一个消息都有一个唯一id,每次消费者消费消息前,先去数据库中查询是否有过对应消息id,如果没有,消费者消费消息后,将消息id存入数据库中,如果有,则为重复消息放弃处理。