https://blog.csdn.net/chenping1993/article/details/114580954
如何解决消息重复消费的问题:
为了保证消息不被重复消费,首先要保证每个消息是唯一的,所以可以给每一个消息携带一个全局唯一的id,流程如下:
1、消费者监听到消息后获取id,先去查询这个id是否存中
2、如果不存在,则正常消费消息,并把消息的id存入 数据库或者redis中(下面的编码示例使用redis)
3、如果存在则丢弃此消息
生产者
/**
* @Description: 发送消息 模拟消息重复消费
* 消息重复消费情景:消息生产者已把消息发送到mq,消息消费者在消息消费的过程中突然因为网络原因或者其他原因导致消息消费中断
* 消费者消费成功后,在给MQ确认的时候出现了网络波动,MQ没有接收到确认,
* 为了保证消息被消费,MQ就会继续给消费者投递之前的消息。这时候消费者就接收到了两条一样的消息
* @param:
* @return: java.lang.String
* @Author: chenping
* @Date: 2021/3/5 17:25
*/
@GetMapping("/rabbitmq/sendMsgNoRepeat")
public String sendMsgNoRepeat() {
String message = "server message sendMsgNoRepeat";
for (int i = 0; i <10000 ; i++) {
Message msg = MessageBuilder.withBody((message+"--"+i).getBytes()).setMessageId(UUID.randomUUID()+"").build();
amqpTemplate.convertAndSend("queueName4",msg);
}
return message;
}
消息消费者服务:
@RabbitListener(queues = "queueName4")//发送的队列名称 @RabbitListener注解到类和方法都可以
@RabbitHandler
public void receiveMessage(Message message) throws UnsupportedEncodingException {
String messageId = message.getMessageProperties().getMessageId();
String msg = new String(message.getBody(),"utf-8");
String messageRedisValue = redisUtil.get("queueName4","");
if (messageRedisValue.equals(messageId)) {
return;
}
System.out.println("消息:"+msg+", id:"+messageId);
redisUtil.set("queueName4",messageId);//以队列为key,id为value
}