使用Redis防止重复发送RabbitMQ消息

devtools/2025/1/20 13:31:52/

问题

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

方法

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

检验是否已经发送

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

java">    public boolean isSend(String messageType, Long bizId, int hashCode) {// 根据消息类型、业务id和哈希值组合成keyString 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

java">    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();}}

发送消息方法

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

java">    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);}}

http://www.ppmy.cn/devtools/152097.html

相关文章

【日志篇】(7.6) ❀ 01. 在macOS下刷新FortiAnalyzer固件 ❀ FortiAnalyzer 日志分析

【简介】FortiAnalyzer 是 Fortinet Security Fabric 安全架构的基础,提供集中日志记录和分析,以及端到端可见性。因此,分析师可以更有效地管理安全状态,将安全流程自动化,并快速响应威胁。具有分析和自动化功能的集成…

Vue 和 uniApp 中 CSS 样式差别

之前一直在做vue2的项目,最近开始uniapp的项目,发现两种项目之间css还是有亿点区别的。 一、布局单位 Vue 2 项目: 通常使用 px 作为主要的长度单位,这是一个绝对单位,在不同设备屏幕上显示的物理尺寸相同。例如&am…

python密码学列置换加密解密程序

1.置换密码 置换密码(Permutation Cipher)又叫换位密码(Transposi-tionCipher),它根据一定的规则重新排列明文,以便打破明文的结构特性。置换密码的特点是保持明文的所有字符不变,只是利用置换打乱了明文字符的位置和次…

source insight函数名注释是什么 source insight如何修改函数名

在程序开发和代码管理中,函数名注释和函数名修改是两个关键环节。Source Insight作为一款功能强大的代码编辑器,提供了丰富的功能来帮助开发者高效完成这些任务。本文将详细探讨“source insight函数名注释是什么 source insight如何修改函数名”,并进一步介绍Source Insigh…

rocketmq基本架构

简介 Name server 负责broker注册、心跳,路由等功能,类似Kafka的ZKname server节点之间不互相通信,broker需要和所有name server进行通信。扩容name server需要重启broker,不然broker不会和name server建立连接producer和consum…

git系列之revert回滚

1. Git 使用cherry-pick“摘樱桃” step 1: 本地切到远程分支,对齐要对齐的base分支,举例子 localmap git pull git reset --hard localmap 对应的commit idstep 2: 执行cherry-pick命令 git cherry-pick abc123这样就会将远程…

RabbitMQ 进阶

文章目录 一、发送者的可靠性 1.1 生产者重试机制:1.2 生产者确认机制: 1.2.1 开启生产者确认:1.2.2 定义 ReturnCallback:1.2.3 定义 ConfirmCallback: 二、MQ 的可靠性 2.1 数据持久化: 2.1.1 交换机持…

PyTorch使用教程(7)-数据集处理

1、基础概念 在PyTorch中,torch.utils.data模块是处理数据集和数据加载的核心工具。以下是该模块中一些基础概念的理解: 1.1 Dataset 定义:Dataset是一个抽象类,用于表示数据集。用户需要通过继承Dataset类并实现其__len__和__…