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

server/2025/1/20 22:33:06/

问题

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

相关文章

游戏引擎学习第83天

回顾 昨天主要集中在实现位图缓存并优化使用。通过将位图缓存起来,避免了在屏幕上逐帧绘制所有内容的问题。具体来说,现在可以将任何需要绘制到屏幕上的内容直接绘制到位图中,类似于使用一系列的组合来生成地面纹理。由于目前的位图复制例程…

k8s pod 中通过service account 访问API Server

创建Role,Rolebinding, Service account 和Pod 创建Role apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: myns name: myrole rules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", …

FIDO2密码钥匙与无密码认证:打造安全便捷的数字世界

在数字化时代,密码曾被视为网络安全的基石,但随着网络攻击手段日益复杂,传统的密码认证方法越来越无法抵御这些挑战。对于用户来说,登录密码不仅繁琐易忘,而且一旦泄露,往往会导致数据泄露,造成…

解决 Error: Invalid or corrupt jarfile day04_studentManager.jar 报错问题

在 Java 开发过程中,我们可能会遇到这样的报错信息:Error: Invalid or corrupt jarfile day04_studentManager.jar。这个错误通常表示 day04_studentManager.jar 文件可能已损坏或无效,下面将为大家详细介绍如何解决这个问题。 一、错误点分…

在 Vue 3 项目中集成和使用 vue3-video-play

前言 随着视频内容的普及,视频播放功能在现代 Web 应用中变得越来越重要。如果你正在开发一个 Vue 3 项目,并且需要快速集成视频播放功能,vue3-video-play 是一个轻量级且易于使用的 Vue 3 组件。本文将介绍如何在 Vue 3 项目中使用 vue3-vi…

数仓建模(五)选择数仓技术栈:Hive ClickHouse 其它

在大数据技术的飞速发展下,数据仓库(Data Warehouse,简称数仓)成为企业处理和分析海量数据的核心工具。市场上主流数仓技术栈丰富,如Hive、ClickHouse、Druid、Greenplum等,对于初学者而言,选择…

【Java 数据导出到 Word实现方案】使用EasyPOI 工具包进行简易的word操作

文章目录 前言工具包调研实现方案主要步骤:1. 导入 EasyPOI 依赖2. 创建 Word 文件3. 添加数据到 Word 文件4. 保存文件到本地 使用过程中可能遇到的问题总结 前言 最近业务方说周报、月报让他们很头疼,每次都要统计数据后,手动录入到word文…

sqlite3.OperationalError: database is locked python-BaseException错误解决

报错有2种: sqlite3.OperationalError: attempt to write a readonly databasesqlite3.OperationalError: database is locked python-BaseException 原因及解决方案: 1、被占用 由于SQLite只支持单线程。SQLite数据库在同一时间只能由一个连接执行写…