问题

今天遇到一个问题,发送MQ消息的时候需要保证不会重复发送,注意不是可靠到达(可靠到达可以通过消息确认机制和回调接口保证),这里保证的是不会生产多条一样的消息。

方法

综合讨论下来决定使用Redis缓存来解决,因为相比于将记录插入数据库Redis更为高效和便捷。

检验是否已经发送

在发送消息之前根据相关信息组合成keyRedis中查找,找到后检测值是否为存在并且是否为设定的值,若存在且与设定的值一样,则返回false,说明该消息已经发送过了。

    public boolean isSend(String messageType, Long bizId, int hashCode) {
// 根据消息类型、业务id和哈希值组合成key
String key = this.genKey(messageType, bizId, hashCode);
Long value = super.get(key); if (value != null && value.equals(DEFAULT_VALUE)) {
return false;
} return true;
} /**get方法*/
public V get(K key) {
if (key == null) {
return null;
} else {
try {
// 在key前添加前缀和名字,并将原来的key进行json序列化
String realKey = this.genRealKey(key);
String content = (String)this.redisTemplate.opsForValue().get(realKey);
// 若get到的值不为null则进行json反序列化
return content == null ? null : this.valueSerializer.deserialize(content);
} catch (Exception e) {
CACHE.error("", key.toString(), "", "0", e);
return null;
}
}
}

以上就是检验消息是否重复的方法,需要注意的是JSON序列化,因为Redis默认使用的是JDK序列化,这种序列化后的内容不仅多而且不易于阅读,因此将其改为Json序列化。

发送后添加缓存

在发送消息的时候会先在Redisput一个以相关信息组合为keyvalue为默认值的记录,过期时间为5min

    public void sendMessage(String messageType, Long bizId, int hashCode) {
super.put(genKey(messageType, bizId, hashCode), DEFAULT_VALUE);
} /**put方法*/
public void put(K key, V value) {
try {
if (key != null && null != value) {
// 进行json序列化
String content = this.valueSerializer.serialize(value);
this.redisTemplate.opsForValue().set(this.genRealKey(key), content, this.expires, this.timeUnit);
}
} catch (Throwable e) {
e.printStackTrace();
}
}

发送消息方法

最后的发送消息方法大致代码如下:

    public void sendMQMessage(Long bizId, String messageTemplateCode, String msg, int msgHashCode, String exchange, String routingKey) {
//加入缓存
boolean send = true;
//String messageType = MessageTypeUtil.getMessageType(messageTemplateCode);
if (bizId != null) {
// 检测是否已经发送
send = sendMessageCache.isSend(messageTemplateCode, bizId, msgHashCode);
} //发送mq消息
if (send) {
if (bizId != null) {
// 加入缓存
sendMessageCache.sendMessage(messageTemplateCode, bizId, msgHashCode);
}
// 发送消息
messageSender.send(exchange, routingKey, msg);
}
}

使用Redis防止重复发送RabbitMQ消息的更多相关文章

  1. RabbitMQ,RocketMQ,Kafka 事务性,消息丢失和消息重复发送的处理策略

    消息队列常见问题处理 分布式事务 什么是分布式事务 常见的分布式事务解决方案 基于 MQ 实现的分布式事务 本地消息表-最终一致性 MQ事务-最终一致性 RocketMQ中如何处理事务 Kafka中如 ...

  2. rabbitmq 重复ACK导致消息丢失

    rabbitmq 重复确认导致消息丢失 背景 rabbitmq 在应用场景中,大多采用工作队列 work-queue的模式. 在一个常见的工作队列模式中,消费者 worker 将不断的轮询从队列中拉取 ...

  3. RabbitMQ系列(四)RabbitMQ事务和Confirm发送方消息确认——深入解读

    RabbitMQ事务和Confirm发送方消息确认--深入解读 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器 ...

  4. RabbitMQ事务和Confirm发送方消息确认

    RabbitMQ事务和Confirm发送方消息确认——深入解读 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器 ...

  5. 在服务端处理同步发送小消息的性能上Kafka>RocketMQ>RabbitMQ

    在发送小消息的场景中,三个消息中间件的表现区分明显: Kafka的吞吐量高达17.3w/s,远超其他两个产品.这主要取决于它的队列模式保证了写磁盘的过程是线性IO.此时broker磁盘IO已达瓶颈. ...

  6. RabbitMQ如何保证发送端消息的可靠投递

    消息发布者向RabbitMQ进行消息投递时默认情况下是不返回发布者该条消息在broker中的状态的,也就是说发布者不知道这条消息是否真的抵达RabbitMQ的broker之上,也因此会发生消息丢失的情 ...

  7. RabbitMQ消息确认(发送确认,接收确认)

    前面几篇记录了收发消息的demo,今天记录下关于 消息确认方面的 问题. 下面是几个问题: 1.为什么要进行消息确认? 2.rabbitmq消息确认 机制是什么样的? 3.发送方如何确认消息发送成功? ...

  8. 【转载】java实现rabbitmq消息的发送接受

    原文地址:http://blog.csdn.net/sdyy321/article/details/9241445 本文不介绍amqp和rabbitmq相关知识,请自行网上查阅 本文是基于spring ...

  9. Rabbitmq消息队列(二) Hello World! 模拟简单发送接收

    1.简介 RabbitMQ是消息代理:它接受和转发消息.你可以把它当作一个邮局:当你把你要邮寄的邮件放在信箱里时,你可以肯定Postman先生最终会把邮件送到你的收件人那里.在这个比喻中,Rabbit ...

  10. 小程序:前端防止用户重复提交&即时消息(IM)重复发送问题解决

    背景: 最近参与开发的小程序,涉及到即时消息(IM)发送的功能: 聊天界面如下,通过键盘上的[发送]按钮,触发消息发送功能 问题发现: 功能开发完毕,进入测试流程:测试工程师反馈说: 在Android ...

随机推荐

  1. LeetCode题目练习记录 _栈、队列01 _20211012

    LeetCode题目练习记录 _栈.队列01 _20211012 84. 柱状图中最大的矩形 难度困难1581 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . ...

  2. 轻量级网络-ShuffleNetv2 论文解读

    摘要 1.介绍 2.高效网络设计的实用指导思想 G1-同样大小的通道数可以最小化 MAC G2-分组数太多的卷积会增加 MAC G3-网络碎片化会降低并行度 G4-逐元素的操作不可忽视 3.Shuff ...

  3. 题解:CF559B Equivalent Strings

    CF559B Equivalent Strings 题解 题目描述 吐槽一下,题目翻译有歧义. 思路分析 你会发现,当你需要判断字符串 \(a,b\) 是否等价时,如果长度为偶数,需要继续判断字符串 ...

  4. 2023年10月,红米(小米)note 8 pro 优化记

    看了红米的note 13 pro和note 12 turbo的参数和价格后,我决定下单买个note8 pro的手机壳,确实有新手机的感觉了. 我note8 pro手机参数如下 MIUI 12.0.5 ...

  5. 只有ip地址没有域名怎么申请https证书

    ​只有IP地址没有域名,如何申请HTTPS证书? 在日常生活中,我们通常会为网站的域名申请HTTPS证书,以保护用户的数据安全.然而,有时候你可能需要为一个只有IP地址的服务或设备申请HTTPS证书. ...

  6. .NET9 - 新功能体验(二)

    书接上回,我们继续来聊聊.NET9和C#13带来的新变化. 01.新的泛型约束 allows ref struct 这是在 C# 13 中,引入的一项新的泛型约束功能,允许对泛型类型参数应用 ref ...

  7. 使用缓存构建更快的 Web 应用程序

    使用 Java 缓存系统缓存频繁查看的数据 使用 Java 技术的 Web 开发人员可以使用缓存实用程序快速提升他们的应用程序的性能.Java 缓存系统(Java Caching System,JCS ...

  8. java——棋牌类游戏五子棋(webwzq1.0)之三(Msg)

    package msg; import java.io.ObjectInputStream; import java.net.DatagramSocket; /******************** ...

  9. 修复Bug好比钓鱼

    作者: Jim Bird  来源: CSDN  发布时间: 2012-09-13 10:43  阅读: 4224 次  推荐: 18   原文链接   [收藏]   英文原文:Fixing a Bug ...

  10. Django+SimpleUI

    1.安装 pip install django-simpleui -i https://pypi.tuna.tsinghua.edu.cn/simple 2.修改配置文件 # 修改project的se ...