Redisson实现简单消息队列:优雅解决缓存清理冲突

news2024/11/23 10:04:55

在项目中,缓存是提高应用性能和响应速度的关键手段之一。然而,当多个模块在短时间内发布工单并且需要清理同一个接口的缓存时,容易引发缓存清理冲突,导致缓存失效的问题。为了解决这一难题,我们采用Redisson的消息队列功能,实现了一个简单而高效的消息队列,优雅地解决了缓存清理冲突问题。本文将为您详细介绍Redisson实现简单消息队列的方案,以及如何在项目中使用它来优化缓存清理。

第一部分:缓存清理冲突的挑战

在高并发场景下,多个模块可能同时发布工单,并且这些工单可能会导致同一个接口的缓存失效。当多个模块同时发起缓存清理请求时,可能会造成数据库压力增大及缓存不一致的问题,降低应用程序的性能和稳定性。这种情况下,我们需要一种优雅的解决方案来协调缓存清理的行为。

第二部分:Redisson简介

Redisson是一个功能强大的Java库,基于Redis构建,它提供了分布式数据结构和服务,以及异步处理的解决方案。其中,消息队列是Redisson提供的一项强大功能,用于在多个模块之间实现高效的消息传递和处理。

第三部分:使用Redisson消息队列解决方案

为了解决缓存清理冲突问题,我们选择使用Redisson的消息队列功能,具体步骤如下:

创建Redisson客户端: 首先,我们需要创建一个Redisson客户端,用于连接到Redis服务器。

创建消息队列: 接下来,我们创建一个Redisson的队列,用于存放缓存清理请求消息。

发布缓存清理请求: 在每个模块发布工单时,我们将对应的缓存清理请求添加到Redisson队列中。

消费缓存清理请求: 我们创建一个定时任务,周期性的从Redisson队列中获取缓存清理请求消息。

处理缓存清理冲突: 合并消息,并执行缓存清理操作,避免多个模块同时清理同一个接口的缓存。

第三部分:代码示例

redisson配置文件

# 项目相关Spring redis配置
spring:
  redisson:
    # 地址
    clusters: 192.168.10.106:6479,192.168.10.106:6579,192.168.10.106:6679
    # 密码
    password: 123456
    # 连接超时时间
    timeout: 10s

客户端连接类: RedissonManager

package cn.xj.redis;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.redisson.config.Config;
import org.redisson.config.ReadMode;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


/**
 * description: redisson初始化
 *
 * @author xj
 * <p>
 * create on 2020-04-09 17:21
 **/
@Configuration
public class RedissonManager {

    @Value("${spring.redisson.clusters}")
    private  String cluster;
    @Value("${spring.redisson.password}")
    private String password;




    @Bean(name="cacheCluster")
    public RedissonClient getRedissonCluster(){
        String[] nodes = cluster.split(",");
        //redisson版本是3.5,集群的ip前面要加上“redis://”,不然会报错,3.2版本可不加
        for(int i=0;i<nodes.length;i++){
            nodes[i] = "redis://"+nodes[i];
        }
        RedissonClient redisson = null;
        Config config = new Config();
        //设置
        config.setCodec(new StringCodec())
                //这是用的集群server
                .useClusterServers()
                //设置集群状态扫描时间
                .setScanInterval(2000)
                .addNodeAddress(nodes)
                .setPassword(password)
                .setReadMode(ReadMode.MASTER);;
        redisson = Redisson.create(config);
        return redisson;
    }

}

redis工具类:RedissonCache


package cn.xj.redis;


import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.Set;


/**
 * redisson工具类
 * company
 * @author
 * @data 2020-04-01
 */
@Component
@Slf4j
public class RedissonCache {



    @Autowired
    @Qualifier("cacheCluster")
    private RedissonClient cacheCluster;

    public boolean cacheAdd(String key, Map<String,Set<String>> message){
        String msgJsonstr = JSONObject.toJSONString(message);
        RQueue<String> queue = cacheCluster.getQueue(key);
        return queue.add(msgJsonstr);
    }

    public Map<String, Set<String>> cachePoll(String key){
        RQueue<String> queue = cacheCluster.getQueue(key);
        String msgJsonstr = queue.poll();
        return JSON.parseObject(msgJsonstr, new TypeReference<Map<String, Set<String>>>() {});
    }

}

功能示例类:QueueController

package cn.xj.redis;

import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

@RestController
public class QueueController {

    private static final String KEY= "xj_test_queue";
    @Autowired
    private RedissonCache redissonCache;

    /**
     * 添加消息队列
     * @param params
     */
    @PostMapping("/redis/queue/add")
    public void add(@RequestBody Map<String, Set<String>> params){
        redissonCache.cacheAdd(KEY,params);
    }


    /**
     * 消费队列中的消息
     * @return
     */
    @GetMapping("/redis/queue/poll")
    public List<Map<String, Set<String>>> poll(){
        List<Map<String, Set<String>>> result = new ArrayList<>();
        //每次最大消费条数
        int batchSize = 200;
        //获取消费的所有消息
        Map<String, Set<String>> msgMap = redissonCache.cachePoll(KEY);
        while (batchSize > 0 && !ObjectUtils.isEmpty(msgMap)) {
            result.add(msgMap);
            batchSize--;
            msgMap = redissonCache.cachePoll(KEY);
        }

        try {
            //消息合并、处理逻辑

            //此处省略代码一万行
        } catch (Exception e){
            
            //消息处理失败的逻辑
        }
        return result;
    }
}

我们调用模拟添加接口可以看到。每次有新的消息都是给queque的尾部添加

_20230724204722.png

每次消费的时候是queque的头部开始取数据

第五部分:总结和应用场景及注意事项

通过Redisson的消息队列功能,我们成功实现了一个简单而高效的缓存清理解决方案。该方案有效解决了多个模块同时发布工单导致缓存清理冲突的问题,提高了应用程序的性能和稳定性。

适用场景:

  • 多个模块在短时间内发布工单,并需要清理同一个接口的缓存。

  • 消息队列可以将不同模块或不同组件之间的通信解耦,实现系统的高内聚和低耦合。同时,在系统面临突发大量请求时,消息队列可以进行削峰填谷,保护系统不受过载影响。

注意事项:

  • 在使用队列时,要考虑队列的容量,避免队列过大导致内存压力过大或队列过小导致消息丢失。

  • 在使用消息队列时,需要小心处理异常情况。例如,如果消息处理失败,可以将消息重新排队或将其放入一个死信队列,以便稍后进行处理。

总结

Redisson的消息队列是解决缓存清理冲突问题的优雅方案,通过其强大的功能,我们可以简单地实现消息传递和处理,从而优化应用程序的性能。在日常开发中,合理应用Redisson的消息队列功能,能够帮助我们处理更多类似的并发问题,提升应用程序的可靠性和扩展性。

希望本文能够为读者提供有益的参考,让您在项目中更加灵活和高效地使用Redisson实现简单消息队列。愿您的应用程序在缓存清理中更上一层楼,助您的项目更加稳健发展!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/786943.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SuperCLUE中文大模型排行榜(2023年7月)

中文通用大模型综合性测评基准&#xff08;SuperCLUE&#xff09;&#xff0c;是针对中文可用的通用大模型的一个测评基准。 它主要要回答的问题是&#xff1a;在当前通用大模型大力发展的情况下&#xff0c;中文大模型的效果情况。包括但不限于&#xff1a;这些模型哪些…

思科设备静态路由配置

一、静态路由基本知识 路由器的主要功能就是用来转发IP 数据包以使数据包到达正确的目的主机。可以想象数据包到达路由器就像一辆汽车开到十字路口&#xff0c;路由表就类似路标&#xff0c;列出可能到达的目的地&#xff0c;以及应该选择哪条路到达目的地。 路由器必须要有相应…

Cesium态势标绘专题-圆形(标绘+编辑)

标绘专题介绍:态势标绘专题介绍_总要学点什么的博客-CSDN博客 入口文件:Cesium态势标绘专题-入口_总要学点什么的博客-CSDN博客 辅助文件:Cesium态势标绘专题-辅助文件_总要学点什么的博客-CSDN博客 本专题没有废话,只有代码,代码中涉及到的引入文件方法,从上面三个链…

Set集合类详解(附加思维导图)

目录 一、Set集合思维导图 二、set集合类常用方法 2.1、HashSet集合常用方法 2.2、TreeSet集合的使用 三、HashSet、LinkedHashSet、TreeSet的使用场景 四、list和set集合的区别 一、Set集合思维导图 二、set集合类常用方法 2.1、HashSet集合常用方法 ①&#xff1a;add…

Docker安装Elasticsearch相关软件安装

Docker安装Elasticsearch相关软件安装 本文将介绍通过 Docker 的方式安装 Elasticsearch 相关的软件。 1、Docker安装Elasticsearch 1.1 搜索镜像 $ docker search elasticsearch $ docker search elasticsearch:7.12.11.2 拉取镜像 $ docker pull elasticsearch:7.12.11.…

# jellyfin安装设置使用散记

jellyfin安装设置使用散记 文章目录 jellyfin安装设置使用散记0 软件简介1 安装2 视频转码问题2.1 局域网转码情况测试&#xff08;不同网段&#xff09;2.2 局域网jellyfin app默认转码问题解决2.3 外网转码情况测试 3 一些坑4 插件5 最后 0 软件简介 Jellyfin 是一个自由的软…

ConcurrentHashMap 相比于 HashMap 的优势

ConcurrentHashMap 使用每个链表头节点作为锁对象, 把一把大锁转换成多把小锁, 大大缩小了锁冲突的概率 HashTable 是给整个 Hash 表加锁, 因此只要有线程抢到了锁其他线程就得阻塞等待. ConcurrentHashMap 是对每个链表加锁, 因此只要不是对同一个链表进行修改就不会阻塞, 大…

linux 查看网卡,网络情况

1&#xff0c;使用nload命令查看 #yum -y install nload 2&#xff0c; 查看eth0网卡网络情况 #nload eth0 Incoming也就是进入网卡的流量&#xff0c;Outgoing&#xff0c;也就是从这块网卡出去的流量&#xff0c;每一部分都有下面几个。 – Curr&#xff1a;当前流量 – Avg…

vue中重新获取数据导致页面加长,要求在页面更新之后浏览器滚动条滚动到之前浏览记录的位置。以及获取当前页面中是哪个元素产生滚动条的方法。

目前的页面样式为&#xff1a; 代码是&#xff1a; <section id"detailSection"><el-tableref"multipleTable":data"logDetailList"style"width: 650px;margin:20px auto;"id"dialogDetail":show-header"fals…

13 QT资源文件导入

导入资源: 1&#xff1a;将资源文件放入到项目目录下 2&#xff1a;添加资源文件 2.1&#xff1a;右键项目->添加新文件->Qt->Qt Resource file ->给资源文件命名 ex: res ->生成res.qrc 3&#xff1a;编辑资源文件 3.1&#xff1a;添加前缀 3.2&#xff1a;…

荧光效率的测试原理-荧光量子效率测试系统

荧光染料是一种新型染料,它既有常规染料的着色特性,又能发射出荧光,使得织物的饱和度和鲜艳度提高,广泛用于纺织、服装等领域。目前,荧光染料在防伪、分子探针等方面的应用也方兴未艾。由于荧光染料在科技和人们的生活中得到了越来越多的应用,对其测配色的研究也引起了颜色学家…

数据中心蓄电池监测,这个方法太好用了!

在数字化时代&#xff0c;数据机房扮演着至关重要的角色&#xff0c;成为企业和组织保障信息安全和业务稳定运行的关键枢纽。 数据中心的可靠性和持续运行并不仅仅依赖于稳定的电力供应&#xff0c;而是需要多层次的保障措施。其中&#xff0c;蓄电池监控系统作为数据中心不可或…

多城市同城分类信息发布h5公众号系统开发

多城市同城分类信息发布h5公众号系统开发 1&#xff1a;分类信息&#xff0c;商户入驻&#xff0c;红包广告&#xff0c;同城动态&#xff0c;代理加盟。 2&#xff1a;全国版&#xff0c;多城市版&#xff0c;本地版自由切换。 3&#xff1a;付费发帖&#xff0c;付费置顶、付…

【高危】Foxit 福昕PDF阅读器 Field Calculate 释放后使用漏洞(PoC)

漏洞描述 Foxit PDF阅读器是福昕软件公司推出的一款广泛使用的PDF文档阅读器。 在受影响版本中&#xff0c;由于其javascript引擎存在use-after-free漏洞&#xff0c;攻击者可以构造恶意的PDF文件&#xff0c;通过文件中包含的deletePages()等操作使福昕PDF阅读器过早删除与页…

2022 年云南省职业院校技能大赛(高职组) “软件测试”赛项竞赛规程

2022 年云南省职业院校技能大赛(高职组) “软件测试”赛项竞赛规程 一、赛项名称 赛项名称&#xff1a;软件测试 赛项组别&#xff1a;高职组 赛项归属产业&#xff1a; 电子信息大类 二、竞赛目的 (一)检验教学成效 本赛项竞赛内容以《国家职业教育改革实施方案》为设计方针…

一百三十三、Hive——Hive外部表加载含有JSON格式字段的CSV文件数据

一、目标 在Hive的ODS层建外部表&#xff0c;然后加载HDFS中的CSV文件数据 注意&#xff1a;CSV文件中含有未解析的JSON格式的字段数据&#xff0c;并且JSON字段中还有逗号 二、第一次建外部表&#xff0c;直接以&#xff0c;分隔行字段&#xff0c;结果JSON数据只显示一部分…

真实和虚拟相撞,构造的VR展厅特点和优势有哪些?

随着科技的不断发展&#xff0c;VR展厅成为了现代展览的一种全新展现方式&#xff0c;三维立体展厅的设计&#xff0c;让企业、画展、纪念展等可以创造出令人惊叹的虚拟展览空间效果&#xff0c;为用户带来丰富的体验。观众身临其境地感受实体展厅和展品&#xff0c;这种超越了…

【Docker-compose】基于Docker-compose创建LNMP环境并运行Wordpress网站平台

基于Docker compose创建LNMP环境并运行Wordpress网站平台 1.Docker-Compose概述2. YAML文件格式及编写注意事项3. Docker-Compose配置常用字段4.Docker Compose常用命令5.使用Docker-compose创建LNMP环境&#xff0c;并运行Wordpress网站平台5.1 Docker Compose环境安装5.2 使用…

苍穹外卖项目解读(一) 完整代码本地部署运行

前言 HM新出springboot入门项目《苍穹外卖》&#xff0c;笔者打算写一个系列学习笔记&#xff0c;“苍穹外卖项目解读”&#xff0c;内容主要从HM课程&#xff0c;自己实践&#xff0c;以及踩坑填坑出发&#xff0c;以技术&#xff0c;经验为主&#xff0c;记录学习&#xff0…

Tensorflow报错protobuf requires Python ‘>=3.7‘ but the running Python is 3.6.8

报错信息 仔细观察下方命令后&#xff0c;可得运行:python -m pip install --upgrade pip即可 完成后再次执行性安装命令 成功&#xff01;&#xff01;&#xff01;