一、幂等性
问题:消费者在消费MQ中的消息时,MQ已把消息发送给消费者,消费者在给MQ返回ACK时网络中断,故MQ未收到确认消息,该消息会重新发送给其他消费者,或者在网络重连后再次发送给消费者,但实际上该消费者已经成功消费了该条消息,造成了消息的重复消费。
解决方案:给消息生成一个全局唯一id,每次消费时判断该消息是否被消费过。
业界主流的两种方式:唯一ID+指纹码机制;利用redis原子性实现
唯一ID+指纹码机制
指纹码:我们的一些规则或者时间戳加别的服务给到的唯一信息码,它不一定是由我们系统生成的,基本都是由我们的业务规则拼接而来的,但是一定要保证唯一性,然后利用查询语句进行判断这个id是否存放在数据库中,优势就是实现一个简单的拼接,然后查询判断是否重复;劣势就是在高并发时,如果是单个数据库就会有写入性能瓶颈和,当然可以采用分库分表提升性能,但也不是最推荐的方式。
Redis原子性
利用Redis执行setnx命令,天然就有幂等性操作,从而实现不重复消费
二、优先级队列
使用场景:订单催付
区间范围:0-255 越大优先级越高
实现:
代码:
对列中添加代码优先级
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-max-priority",10);
return QueueBuilder.durable("queue1").withArguments(arguments).build();
消息中添加代码优先级
msg.getMessageProperties().setPriority(5);
注意:必须队列和消息同时设置优先级才可以
三、惰性队列
惰性队列:消息保存在磁盘上
使用场景:消费者下线,宕机或者由于维护而关闭而致使长时间内不能消费消息造成消息堆积时使用
两种模式:default和lazy
声明方式:
代码
Map<String,Object> arguments = new HashMap<>();
arguments.put("x-queue-mode","lazy");
channel.queueDeclare("myqueue",false,false,false,arguments);
界面设置