Redisson实现简单消息队列:优雅解决缓存清理冲突
在项目中,缓存是提高应用性能和响应速度的关键手段之一。然而,当多个模块在短时间内发布工单并且需要清理同一个接口的缓存时,容易引发缓存清理冲突,导致缓存失效的问题。为了解决这一难题,我们采用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";@Autowiredprivate 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的尾部添加
每次消费的时候是queque的头部开始取数据
第五部分:总结和应用场景及注意事项
通过Redisson的消息队列功能,我们成功实现了一个简单而高效的缓存清理解决方案。该方案有效解决了多个模块同时发布工单导致缓存清理冲突的问题,提高了应用程序的性能和稳定性。
适用场景:
-
多个模块在短时间内发布工单,并需要清理同一个接口的缓存。
-
消息队列可以将不同模块或不同组件之间的通信解耦,实现系统的高内聚和低耦合。同时,在系统面临突发大量请求时,消息队列可以进行削峰填谷,保护系统不受过载影响。
注意事项:
-
在使用队列时,要考虑队列的容量,避免队列过大导致内存压力过大或队列过小导致消息丢失。
-
在使用消息队列时,需要小心处理异常情况。例如,如果消息处理失败,可以将消息重新排队或将其放入一个死信队列,以便稍后进行处理。
总结
Redisson的消息队列是解决缓存清理冲突问题的优雅方案,通过其强大的功能,我们可以简单地实现消息传递和处理,从而优化应用程序的性能。在日常开发中,合理应用Redisson的消息队列功能,能够帮助我们处理更多类似的并发问题,提升应用程序的可靠性和扩展性。
希望本文能够为读者提供有益的参考,让您在项目中更加灵活和高效地使用Redisson实现简单消息队列。愿您的应用程序在缓存清理中更上一层楼,助您的项目更加稳健发展!
相关文章:

Redisson实现简单消息队列:优雅解决缓存清理冲突
在项目中,缓存是提高应用性能和响应速度的关键手段之一。然而,当多个模块在短时间内发布工单并且需要清理同一个接口的缓存时,容易引发缓存清理冲突,导致缓存失效的问题。为了解决这一难题,我们采用Redisson的消息队列…...
php-golang-rpc 简单的jsonrpc实践
golang代码: package main import ( "net" "net/rpc" "net/rpc/jsonrpc" ) type App struct{} type Res struct { Code int json:"code" Msg string json:"msg" Data any json:"data" } fun…...

Apipost变量高亮展示,变量操作更流畅
之前Apipost配置的各种环境变量只能在右上角环境管理中查看,很多小伙伴希望能有一种更好的解决方案用以快速复制变量值,快速查看变量的当前值和初始值,于是在Apipost 7.1.7中我们推出环境变量高亮展示功能来满足用户的使用需求。 功能描述&a…...

SSIS对SQL Server向Mysql数据转发表数据 (完结)
1、对于根据主键进行更新和插入新的数据,根据前面的文章,对于组件已经很熟悉了,我们直接加入一个 查找 组件 ,如下所示 2、右键点击"查找",然后“编辑” ,选择“连接”,选中我们的目标连接器&…...

vue+Element-ui实现树形组件、表格树
需求 要做出如下图所示的 树形表格,也就是数据之间有父子类关系的这种,可以点击展开、收缩 像上图这样的表格树 实现 1.使用树形组件 在学习树形表格之前,肯定得先搞懂普通的树形组件是怎么搞的,然后将其套到表格中就好了&…...

【iPadOS 开发】打开 iPad 的开发者模式的方法
文章目录 1. 前提条件2. 具体方法 1. 前提条件 iPad 通过 Type-C 线连接到 Mac Mac上已经安装 Xcode 2. 具体方法 在 Xcode 顶栏中的 Window 中打开 Devices and Simulators ,可以看到自己的设备: 接着在 iPad 上进入 设置 > 隐私与安全性 > 开…...
矩阵对角线元素的和
题目: 给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例: 输入:mat [[1,2,3], [4,5,6], [7,8,9]] 输出ÿ…...

看了这篇文章,我也会用grid布局了
grid网格布局 网格布局是由一系列水平及垂直的线构成的一种布局模式,使用网格,我们能够将设计元素进行排列,帮助我们设计一系列具有固定位置以及宽度的元素的页面,使我们的网站页面更加统一。 它将网页划分成一个个网格ÿ…...

{“msg“:“invalid token“,“code“:401}
项目场景: 提示:这里简述项目相关背景: {“msg“:“invalid token“,“code“:401} 前端请求 后端接口时, 请求失败,控制台出现如下所示报错信息 问题描述 问题: 控制台报错信息如下所示: …...
Qt Qml自定义模态对话框
自带的messagedialog不好使,自定义一个,简单的: DialogPop.qml /*** brief 功能:此文件实现了模态框* author lanmanck* date 2023-07-25* CopyRight (C) lanmanck*/ import QtQuick 2.1 import QtQuick.Window 2.0 import QtQu…...
【前端知识】React 基础巩固(三十)——CSS编写方式
React 基础巩固(三十)——CSS编写方式 1.内联样式 Style 接受一个采用小驼峰命名属性的JS对象,而不是CSS字符串 可以引用state中的状态来设置相关的样式 优点:样式之间不会有冲突;可以动态获取当前state中的状态 缺点:需要使用…...
Langchain 集成 FAISS
Langchain 集成 FAISS 1. FAISS2. Similarity Search with score3. Saving and loading4. Merging5. Similarity Search with filtering 1. FAISS Facebook AI Similarity Search (Faiss)是一个用于高效相似性搜索和密集向量聚类的库。它包含的算法可以搜索任意大小的向量集&a…...

科技与人元宇宙论坛跨界对话
近来,“元宇宙”成为热门话题,越来越频繁地出现在人们的视野里。大家都在谈论它,但似 乎还没有一个被所有人认同的定义。元宇宙究竟是什么?未来它会对我们的工作和生活带来什么样 的改变?当谈论虚拟现实(VR…...
JAVA-生成二维码图片
使用hutool工具包,主动一个简单方便,pom添加依赖 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.12</version> </dependency> 直接上代码 //设置像素宽高 QrConfig config new…...

【iOS】iOS持久化
文章目录 一. 数据持久化的目的二. iOS中数据持久化方案三. 数据持有化方式的分类1. 内存缓存2. 磁盘缓存SDWebImage缓存 四. 沙盒机制的介绍五. 沙盒目录结构1. 获取应用程序的沙盒路径2. 访问沙盒目录常用C函数介绍3. 沙盒目录介绍 六. 持久化数据存储方式1. XML属性列表2. P…...

基于Javaweb+Vue3实现淘宝卖鞋前后端分离项目
前端技术栈:HTMLCSSJavaScriptVue3 后端技术栈:JavaSEMySQLJDBCJavaWeb 文章目录 前言1️⃣登录功能登录后端登录前端 2️⃣商家管理查询商家查询商家后端查询商家前端 增加商家增加商家后端增加商家前端 删除商家删除商家后端删除商家前端 修改商家修改…...
bat一键批量、有序启动jar
将脚本文件后缀改为 bat,脚本文件和 jar 包放在同一个目录 echo offstart cmd /c "java -jar register.jar " ping 192.0.2.2 -n 1 -w 10000 > nulstart cmd /c "java -jar admin.jar " ping 192.0.2.2 -n 1 -w 30000 > nulstart cmd /c…...

centos7安装mysql数据库详细教程及常见问题解决
mysql数据库详细安装步骤 1.在root身份下输入执行命令: yum -y update 2.检查是否已经安装MySQL,输入以下命令并执行: mysql -v 如出现-bash: mysql: command not found 则说明没有安装mysql 也可以输入rpm -qa | grep -i mysql 查看是否已…...
C++ STL sort函数的底层实现
C STL sort函数的底层实现 sort函数的底层用到的是内省式排序以及插入排序,内省排序首先从快速排序开始,当递归深度超过一定深度(深度为排序元素数量的对数值)后转为堆排序。 先来回顾一下以上提到的3中排序方法: 快…...
ICP算法和优化问题详细公式推导
1. 介绍 ICP(Iterative Closest Point):求一组平移和旋转使得两个点云之间重合度尽可能高。 2. 算法流程 找最近邻关联点,求解 R , t R , t R , t R , t R,tR,tR,tR,t R,tR,tR,tR,t,如此反复直到重合程度足够高。 3. 数学描述 X { x 1 ,…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...