问题

今天遇到一个问题,发送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. 使用 VSCode 远程连接的 SSH 权限问题及解决方案

    在使用 VSCode 远程 SSH 连接时,可能会遇到文件权限问题导致连接失败的情况.本文将详细记录如何为 SSH 配置文件(config)和私钥文件(id_rsa)正确设置权限,从而解决 VSCod ...

  2. Taylor series Explicit Euler Implicit Euler

    1 Taylor series \[\begin{gathered}\sum_{n=0}^{\infty}\frac{f^{(n)}\left(a\right)}{n!}\left(x-a\right ...

  3. Value error: 'ascii' codec can't decode byte 0xe6 in position 26: ordinal not in range(128) The traceback for the exception was written to the log file

    原因:工作空间中有中文编码问题,导致的运行ros异常 解决办法: 1.解决urdf生成异常问题 urdf文件中不允许有中文,所有当输入中文的时候容易出问题,解决方案: ①在根目录下:/opt/ros/ ...

  4. C# 利用epplus导出excel,自动求和

    /// <summary> /// 生成xlsx /// </summary> /// <param name="dvLine">数据视图< ...

  5. 【斩虫】Hadoop中作业执行刚开始就挂掉的两种情况

    开门见山. 最近在搭建基于 Hadoop 3.3.6 的高可用集群时,遇到了虽然守护进程能正常启动,但是提交 WordCount 示例程序后作业没有办法启动执行的情况(刚开始就挂了),查看日志发现主要 ...

  6. Power BI DAX 公式使用

    一.日期类 1.计算两个日期之间的差值 使用函数:DateDiff(< start_date >,< end_date >.<间隔>) 例:合同终止天数 = DAT ...

  7. Scala代码练习

    1.编程实现百分制转换成五级制,规则如下: 90~100分,返回优秀: 80~89分,返回良好: 70~79分,返回中等: 60~69分,返回及格: 60分以下,返回不及格. object grade ...

  8. 常见return错误

    常见return错误 3221225477 (0xC0000005): 访问越界,一般是读或写了野指针指向的内存. 3221225725 (0xC00000FD): 堆栈溢出,一般是无穷递归造成的. ...

  9. 使用wxpython开发跨平台桌面应用,动态工具的创建处理

    在我们开发系统的时候,往往需要一个很容易理解功能的工具栏,工具栏是一个系统的快速入口,美观易用的工具栏是可以给系统程序增色不少的,本篇随笔介绍在使用wxpython开发跨平台桌面应用,工具栏的动态展现 ...

  10. Nuxt.js 应用中的 webpack:compiled 事件钩子

    title: Nuxt.js 应用中的 webpack:compiled 事件钩子 date: 2024/11/23 updated: 2024/11/23 author: cmdragon exce ...