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

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的尾部添加

_20230724204722.png

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

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

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

适用场景:

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

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

注意事项:

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

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

总结

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

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

相关文章:

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

在项目中&#xff0c;缓存是提高应用性能和响应速度的关键手段之一。然而&#xff0c;当多个模块在短时间内发布工单并且需要清理同一个接口的缓存时&#xff0c;容易引发缓存清理冲突&#xff0c;导致缓存失效的问题。为了解决这一难题&#xff0c;我们采用Redisson的消息队列…...

php-golang-rpc 简单的jsonrpc实践

golang代码&#xff1a; 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配置的各种环境变量只能在右上角环境管理中查看&#xff0c;很多小伙伴希望能有一种更好的解决方案用以快速复制变量值&#xff0c;快速查看变量的当前值和初始值&#xff0c;于是在Apipost 7.1.7中我们推出环境变量高亮展示功能来满足用户的使用需求。 功能描述&a…...

SSIS对SQL Server向Mysql数据转发表数据 (完结)

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

vue+Element-ui实现树形组件、表格树

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

【iPadOS 开发】打开 iPad 的开发者模式的方法

文章目录 1. 前提条件2. 具体方法 1. 前提条件 iPad 通过 Type-C 线连接到 Mac Mac上已经安装 Xcode 2. 具体方法 在 Xcode 顶栏中的 Window 中打开 Devices and Simulators &#xff0c;可以看到自己的设备&#xff1a; 接着在 iPad 上进入 设置 > 隐私与安全性 > 开…...

矩阵对角线元素的和

题目&#xff1a; 给你一个正方形矩阵 mat&#xff0c;请你返回矩阵对角线元素的和。 请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。 示例&#xff1a; 输入&#xff1a;mat [[1,2,3], [4,5,6], [7,8,9]] 输出&#xff…...

看了这篇文章,我也会用grid布局了

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

{“msg“:“invalid token“,“code“:401}

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; {“msg“:“invalid token“,“code“:401} 前端请求 后端接口时&#xff0c; 请求失败&#xff0c;控制台出现如下所示报错信息 问题描述 问题&#xff1a; 控制台报错信息如下所示&#xff1a; …...

Qt Qml自定义模态对话框

自带的messagedialog不好使&#xff0c;自定义一个&#xff0c;简单的&#xff1a; DialogPop.qml /*** brief 功能&#xff1a;此文件实现了模态框* 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对象&#xff0c;而不是CSS字符串 可以引用state中的状态来设置相关的样式 优点&#xff1a;样式之间不会有冲突&#xff1b;可以动态获取当前state中的状态 缺点&#xff1a;需要使用…...

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…...

科技与人元宇宙论坛跨界对话

近来&#xff0c;“元宇宙”成为热门话题&#xff0c;越来越频繁地出现在人们的视野里。大家都在谈论它&#xff0c;但似 乎还没有一个被所有人认同的定义。元宇宙究竟是什么&#xff1f;未来它会对我们的工作和生活带来什么样 的改变&#xff1f;当谈论虚拟现实&#xff08;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实现淘宝卖鞋前后端分离项目

前端技术栈&#xff1a;HTMLCSSJavaScriptVue3 后端技术栈&#xff1a;JavaSEMySQLJDBCJavaWeb 文章目录 前言1️⃣登录功能登录后端登录前端 2️⃣商家管理查询商家查询商家后端查询商家前端 增加商家增加商家后端增加商家前端 删除商家删除商家后端删除商家前端 修改商家修改…...

bat一键批量、有序启动jar

将脚本文件后缀改为 bat&#xff0c;脚本文件和 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身份下输入执行命令&#xff1a; yum -y update 2.检查是否已经安装MySQL&#xff0c;输入以下命令并执行&#xff1a; mysql -v 如出现-bash: mysql: command not found 则说明没有安装mysql 也可以输入rpm -qa | grep -i mysql 查看是否已…...

C++ STL sort函数的底层实现

C STL sort函数的底层实现 sort函数的底层用到的是内省式排序以及插入排序&#xff0c;内省排序首先从快速排序开始&#xff0c;当递归深度超过一定深度&#xff08;深度为排序元素数量的对数值&#xff09;后转为堆排序。 先来回顾一下以上提到的3中排序方法&#xff1a; 快…...

ICP算法和优化问题详细公式推导

1. 介绍 ICP(Iterative Closest Point)&#xff1a;求一组平移和旋转使得两个点云之间重合度尽可能高。 2. 算法流程 找最近邻关联点&#xff0c;求解 R , t R , t R , t R , t R,tR,tR,tR,t R,tR,tR,tR,t&#xff0c;如此反复直到重合程度足够高。 3. 数学描述 X { x 1 ,…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

无法与IP建立连接,未能下载VSCode服务器

如题&#xff0c;在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈&#xff0c;发现是VSCode版本自动更新惹的祸&#xff01;&#xff01;&#xff01; 在VSCode的帮助->关于这里发现前几天VSCode自动更新了&#xff0c;我的版本号变成了1.100.3 才导致了远程连接出…...

基于数字孪生的水厂可视化平台建设:架构与实践

分享大纲&#xff1a; 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年&#xff0c;数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段&#xff0c;基于数字孪生的水厂可视化平台的…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文&#xff5c;DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色&#xff0c;华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型&#xff0c;能助力我们轻松驾驭 DeepSeek-V3/R1&#xff0c;本文中将分享如何…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

Android第十三次面试总结(四大 组件基础)

Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成&#xff0c;用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机&#xff1a; ​onCreate()​​ ​调用时机​&#xff1a;Activity 首次创建时调用。​…...

Python 包管理器 uv 介绍

Python 包管理器 uv 全面介绍 uv 是由 Astral&#xff08;热门工具 Ruff 的开发者&#xff09;推出的下一代高性能 Python 包管理器和构建工具&#xff0c;用 Rust 编写。它旨在解决传统工具&#xff08;如 pip、virtualenv、pip-tools&#xff09;的性能瓶颈&#xff0c;同时…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...