当前位置: 首页 > article >正文

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

问题

今天遇到一个问题,发送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);
        }
    }

http://www.kler.cn/a/505232.html

相关文章:

  • Banana Pi BPI-RV2 RISC-V路由开发板采用矽昌通信SF2H8898芯片
  • 计算机视觉与深度学习:使用深度学习训练基于视觉的车辆检测器(MATLAB源码-Faster R-CNN)
  • Vue如何构建项目
  • 【Vim Masterclass 笔记13】第 7 章:Vim 核心操作之——文本对象与宏操作 + S07L28:Vim 文本对象
  • 【数字化】华为-用变革的方法确保规划落地
  • 提供的 IP 地址 10.0.0.5 和子网掩码位 /26 来计算相关的网络信息
  • C/C++新春烟花
  • UE_C++ —— UE反射系统
  • Quinlan C4.5剪枝U(0,6)U(1,16)等置信上限如何计算?
  • A4.Springboot-LLama3.2服务自动化构建(一)——构建docker镜像配置
  • 安装 MySQL 数据库
  • Java面试总结(1)
  • 迅翼SwiftWing | ROS 固定翼开源仿真平台正式发布!
  • 2Spark Core
  • 昇腾部署onnx模型问题总结
  • ubuntu18.04开发环境下samba服务器的搭建
  • Pcl联合Qt显示点云
  • EF Core执行原生SQL语句
  • Python爬虫实战:从抓取年报并分析数据开始
  • [leetcode]链表基础回顾
  • Hadoop开发过程中15个常见问题的详细解决方案
  • 智能网联汽车的数据脱敏
  • 使用Spring BootSpring AI快速构建AI应用程序
  • 从 MySQL 到 ClickHouse 的迁移与优化——支持上亿级数据量的复杂检索
  • JavaSE学习心得(多线程与网络编程篇)
  • 【Rust】结构体示例与调试