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

embedded/2025/1/23 15:49:25/

问题

今天遇到一个问题,发送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/embedded/156335.html

相关文章

Docker 国内镜像源

目录 概述 步骤 参考资料 概述 自 2024-06-06 开始,阿里,腾讯、中科大等国内的 Docker Hub 镜像加速器相继停止服务,总结了网友整理出来一些其他国内 Docker Hub 镜像源,经过测试可以使用。 步骤 配置 Docker 守护程序 修改…

Kubectl常用命令操作

kubectl 命令格式: kubectl command type name command:表示子命令,用于操作kubernetes的集群资源对象,如:create delete describe get apply type:资源对象的类型 name:资源对象的名称 1.创建资源对象 kubectl create -f my…

Blazor-Blazor WebAssmbly项目结构(上)

创建项目 今天我们来创建一个BlazorWebAssmbly项目,来看看项目结构是如何得,我们创建带模板得项目,会创建出一个demo,来看看项目结构。 创建的项目可以直接启动运行,首次启动会看见加载的过程,这个过程…

自定义BeanPostProcessor实现自动注入标注了特定注解的Bean

定义注解 Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented public interface MyAnno { }定义一个配置类 Configuration public class RestConfig {MyAnnoBeanpublic PayDTO payDTO(){PayDTO payDTO …

mikrotik7配置内网到内网的lantolan

lan to lan又称site to site,在前面的文章已经配置wireguard实现单个ip互访,这期来实现lan to lan 客户端依然使用windows。本期在上一篇基础上增加配置 一、LAN to LAN配置 windows客户端修改 我的第一个内网网段是192.168.11.0/24,以下为相关修改 …

詳細講一下在RN(ReactNative)中,6個比較常用的組件以及詳細的用法

1.View 组件&#xff08;基础容器&#xff09; import { View, StyleSheet } from react-native;const MyComponent () > {return (<View style{styles.container} // 样式pointerEvents"none" // 控制触摸事件&#xff1a;none, box-none, box-only, …

(2025,BioLM,综述)用于生物信息学的 LLM

Large Language Models for Bioinformatics 目录 0. 摘要 1. 引言 2. 生物信息学中语言模型与基础模型的背景 2.1 语言模型与生物信息学基础概述 2.1.1 LLM 与基础模型 2.1.2 生物信息学的应用与挑战 2.2 训练方法与模型 2.2.1 预训练 2.2.2 RLHF 2.2.3 知识蒸馏 …

政府机构如何使用六西格玛来提高效率和提供更好的服务

联邦机构面临着改善运作、降低成本和确保向公民提供高质量服务的巨大压力。六西格玛方法与Minitab强大的工具相结合&#xff0c;使政府组织能够充满信心地应对这些挑战。通过简化流程、减少浪费和改进决策&#xff0c;政府团队可以提供真正有影响力的服务。 六西格玛如何改善政…