使用Redis防止重复发送RabbitMQ消息
问题
今天遇到一个问题,发送MQ消息的时候需要保证不会重复发送,注意不是可靠到达(可靠到达可以通过消息确认机制和回调接口保证),这里保证的是不会生产多条一样的消息。
方法
综合讨论下来决定使用Redis缓存来解决,因为相比于将记录插入数据库Redis更为高效和便捷。
检验是否已经发送
在发送消息之前根据相关信息组合成key去Redis中查找,找到后检测值是否为存在并且是否为设定的值,若存在且与设定的值一样,则返回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序列化。
发送后添加缓存
在发送消息的时候会先在Redis中put一个以相关信息组合为key,value为默认值的记录,过期时间为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消息的更多相关文章
- RabbitMQ,RocketMQ,Kafka 事务性,消息丢失和消息重复发送的处理策略
消息队列常见问题处理 分布式事务 什么是分布式事务 常见的分布式事务解决方案 基于 MQ 实现的分布式事务 本地消息表-最终一致性 MQ事务-最终一致性 RocketMQ中如何处理事务 Kafka中如 ...
- rabbitmq 重复ACK导致消息丢失
rabbitmq 重复确认导致消息丢失 背景 rabbitmq 在应用场景中,大多采用工作队列 work-queue的模式. 在一个常见的工作队列模式中,消费者 worker 将不断的轮询从队列中拉取 ...
- RabbitMQ系列(四)RabbitMQ事务和Confirm发送方消息确认——深入解读
RabbitMQ事务和Confirm发送方消息确认--深入解读 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器 ...
- RabbitMQ事务和Confirm发送方消息确认
RabbitMQ事务和Confirm发送方消息确认——深入解读 RabbitMQ系列文章 RabbitMQ在Ubuntu上的环境搭建 深入了解RabbitMQ工作原理及简单使用 RabbitMQ交换器 ...
- 在服务端处理同步发送小消息的性能上Kafka>RocketMQ>RabbitMQ
在发送小消息的场景中,三个消息中间件的表现区分明显: Kafka的吞吐量高达17.3w/s,远超其他两个产品.这主要取决于它的队列模式保证了写磁盘的过程是线性IO.此时broker磁盘IO已达瓶颈. ...
- RabbitMQ如何保证发送端消息的可靠投递
消息发布者向RabbitMQ进行消息投递时默认情况下是不返回发布者该条消息在broker中的状态的,也就是说发布者不知道这条消息是否真的抵达RabbitMQ的broker之上,也因此会发生消息丢失的情 ...
- RabbitMQ消息确认(发送确认,接收确认)
前面几篇记录了收发消息的demo,今天记录下关于 消息确认方面的 问题. 下面是几个问题: 1.为什么要进行消息确认? 2.rabbitmq消息确认 机制是什么样的? 3.发送方如何确认消息发送成功? ...
- 【转载】java实现rabbitmq消息的发送接受
原文地址:http://blog.csdn.net/sdyy321/article/details/9241445 本文不介绍amqp和rabbitmq相关知识,请自行网上查阅 本文是基于spring ...
- Rabbitmq消息队列(二) Hello World! 模拟简单发送接收
1.简介 RabbitMQ是消息代理:它接受和转发消息.你可以把它当作一个邮局:当你把你要邮寄的邮件放在信箱里时,你可以肯定Postman先生最终会把邮件送到你的收件人那里.在这个比喻中,Rabbit ...
- 小程序:前端防止用户重复提交&即时消息(IM)重复发送问题解决
背景: 最近参与开发的小程序,涉及到即时消息(IM)发送的功能: 聊天界面如下,通过键盘上的[发送]按钮,触发消息发送功能 问题发现: 功能开发完毕,进入测试流程:测试工程师反馈说: 在Android ...
随机推荐
- ajax下载二进制文件(导出Excel)
var url = 'http://127.0.0.1'; var xhr = new XMLHttpRequest(); xhr.open('GET', url, true); // 也可以使用PO ...
- uni-app 监听返回按钮
前置条件: 开发环境:windows 开发框架:uni-app , H5+,nativeJS 编辑器:HbuilderX 2.8.13 4. 兼容版本:安卓,IOS已作测试 进入正题: 文档地址uni ...
- 构建自己的DEX
构建自己的DEX 简介:用户可通过主流钱包Dapp浏览器,访问URL地址,进行Swap, BSC链 界面演示 技术栈 Solidity React Typescript Vite Wagmi Open ...
- 2022/1/25-2022牛客寒假算法基础集训营1B-炸鸡块君与FIFA22(线段树)
题目描述 热爱足球(仅限游戏)的炸鸡块君最近购买了FIFA22,并且沉迷于FIFA22的Rivals排位上分. 在该排位系统中,每局游戏可能有胜利(用W表示).失败(用L表示).平局(用D表示)三种结 ...
- 深度学习系列之1----直观解释Transformer
Abstract 这个系列主要用来记录我自己这种的AI小白的学习之路,通过将所学所知总结下来,记录下来.之前总喜欢记录在笔记本上,或者ipad上,或者PC端的Typora上,但总是很难回头检索到一些系 ...
- 2款使用.NET开发的数据库系统
前言 今天大姚给大家分享2款使用.NET开发且开源的数据库系统. Garnet Garnet是一款由微软研究院基于.NET开源的高性能.跨平台的分布式缓存存储数据库,该项目提供强大的性能(吞吐量和延迟 ...
- Wgpu图文详解(02)渲染管线与着色器
在本系列的第一篇文章中(<Wgpu图文详解(01)窗口与基本渲染>),我们介绍了如何基于0.30+版本的winit搭建Wgpu的桌面环境,同时也讲解了关于Wgpu一些基本的概念.模块以及架 ...
- PicGo+CloudFire搭建免费图床
目录 CloudFire对象存储 创建bucket 配置域名 配置 Bucket 访问 API PicGO配置 参考博客 CloudFire对象存储 | CloudFire提供对象存储服务,每个月有1 ...
- pjsip编译、说明及vs2022使用示例
环境: window10_x64 & vs2022 pjsip版本: 2.14.1 之前整理过pjsip 2.10的编译及python使用示例: https://www.cnblogs.c ...
- Air780E软件指南:C语言内存数组(zbuff)
一.ZBUFF(C内存数组)简介 zbuff库可以用c风格直接操作(下标从0开始),例如buff[0]=buff[3] 可以在sram上或者psram上申请空间,也可以自动申请(如存在psram则在p ...