高效协作处理缓存清理需求:生产者-消费者模式助力多模块缓存管理

news2024/9/28 11:07:59

在现代应用系统中,缓存是提高性能和减少数据库负载的重要手段之一。然而,缓存的数据在某些情况下可能会过期或者变得无效,因此需要及时进行清理。在复杂的应用系统中,可能有多个系统、多个模块产生缓存清理需求,而这些系统、模块之间的清理任务需要高效的协作,以避免数据竞争和资源浪费的问题。

本文将介绍一种高效处理多模块缓存清理需求的方案,通过使用Redis消息队列,采用生产者-消费者模式,实现了多个系统、多个模块的消息生产和消费任务的合理协作。在这个方案中,多个系统、多个模块可以同时生产清理缓存的消息,消费者定期获取并合并这些消息后,通过多线程进行缓存清理,从而达到高效处理的目的。

生产者-消费者模式

生产者-消费者模式是一种经典的多线程设计模式,用于解决多个生产者和消费者之间的协作问题。生产者负责生成数据,并将其放入共享缓冲区,而消费者则负责从缓冲区中取出数据并进行处理。这种模式的目标是确保生产者和消费者之间的有效沟通和数据交换,从而避免竞态条件和数据不一致问题。

方案介绍

-2023-06-29-2157.png

Redis是一种高性能的内存数据库,同时也是一个强大的消息中间件。Redis支持多种数据结构,包括List(列表)和Queue(队列),这些数据结构可以用于实现消息队列的功能。

在Redis中,多个系统、多个模块可以将清理缓存的消息作为生产者生产,并将这些消息添加到一个特定的Queue中。而缓存清理服务则定期从这个Queue中获取消息,进行合并后再多个消费者进行缓存清理操作。这种模式称为生产者-消费者模式,它实现了生产者和消费者的解耦,使得多个系统、多个模块之间可以独立进行消息的生产,由缓存清理服务统一多线程进行消息的消费,从而提高系统的灵活性和可维护性,使得业务系统于消息缓存系统之间不存在耦合关系。

第一步: 初始化Redis连接和消息队列

首先,需要在应用程序中初始化Redis连接,以便于生产者和消费者能够连接到Redis数据库。同时,创建一个消息队列,用于存储多个系统、多个模块产生的清理缓存的消息。

第二步: 系统或模块生产消息

每个模块可以根据自己的清理缓存需求,产生对应的清理缓存消息,并将消息添加到Redis的消息队列中。

MsgProduct

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Set;

@Service
@Slf4j
public class MsgProduct {

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

    public boolean msgAdd(Map<String, Set<String>> params){
        //生产消息
        return redissonCache.cacheAdd(KEY,params);
    }
}

第三步: 消费者定期获取并合并消息,多线程缓存清理

消费者定期从Redis消息队列中获取缓存清理消息。获取到的消息可以按照namespace进行分类合并,以便后续多线程消费时能够分别处理不同模块的缓存清理任务。

MsgConsumer

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class MsgConsumer {
    private static final String KEY= "xj_test_queue";
    @Resource
    private RedissonCache redissonCache;

    public void poll(){
        Map<String, Set<String>> params = new LinkedHashMap<>();
        Map<String, Set<String>> msgMap = redissonCache.cachePoll(KEY);
        int batchSize = 500;

        String namespace;
        Set<String> msgSet;
        Set<String> mergedSet;

        while (batchSize > 0 && !ObjectUtils.isEmpty(msgMap)) {
            // 合并消息
            for (Map.Entry<String, Set<String>> entry : msgMap.entrySet()) {
                namespace = entry.getKey();
                msgSet = entry.getValue();
                mergedSet = params.getOrDefault(namespace, new HashSet<>());
                mergedSet.addAll(msgSet);
                params.put(namespace, mergedSet);
            }
            batchSize--;
            msgMap = redissonCache.cachePoll(KEY);
        }

        // 创建线程池
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                10,
                15,
                60L,
                TimeUnit.MILLISECONDS,
                new ArrayBlockingQueue<>(10)
        );
        for (Map.Entry<String, Set<String>> entry : params.entrySet()) {
            executor.execute(()-> this.doFlush(entry.getKey(),entry.getValue()) );
        }

    }

    public void doFlush(String namespace,Set<String> provinces){
        try {
            //执行缓存清理逻辑
            log.info("清理缓存的接口编码为:{},省份编码为:{}",namespace,provinces);
        }catch (Exception e){
            //缓存清理失败处理逻辑
            log.error("清理缓存失败",e);
        }

    }

}

优势与收益

采用基于Redis消息队列的生产者-消费者模式,我们成功解决了多个模块缓存清理的高效协作问题。这种模式的优势在于:

  1. 提高性能与并发处理能力: 多线程并发消费消息,加速缓存清理任务的执行,提高系统的整体性能。

  2. 灵活扩展: 不同模块可以独立生产和消费消息,系统的可扩展性大大增强。

  3. 数据一致性: 通过合理的消息合并策略,保证缓存清理任务的数据一致性。

  4. 资源节约: 避免资源浪费和重复清理,提高系统的资源利用率。

结语

在复杂的应用系统中,多个系统、多个模块可能会同时产生缓存清理需求。基于Redis消息队列的生产者-消费者模式为这种场景提供了一种高效协作处理方案。通过生产者生产消息、消费者定期获取合并消息并进行多线程消费,系统可以高效处理缓存清理任务,保证数据的一致性和并发安全性。这种设计模式在当今大数据和高并发的背景下尤其重要,对于提升系统性能和稳定性具有积极意义。

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

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

相关文章

从实践彻底掌握MySQL的主从复制

目录 一、本次所用结构如图---一主多从级联&#xff1a; 二、IP。 三、配置M1&#xff1a; 四、从库M1S1&#xff1a; 五、从库M2配置&#xff1a; 六、 从库M2S1&#xff1a; 一、本次所用结构如图--- 一主多从级联&#xff1a; 二、IP。这里M1S1和M1S2一样的&#xff0…

怎么学习Java框架和库相关知识? - 易智编译EaseEditing

学习Java框架和库相关知识可以遵循以下步骤&#xff1a; 确定学习方向&#xff1a; Java拥有众多的框架和库&#xff0c;例如Spring、Hibernate、JavaFX、Apache Commons等。首先确定你感兴趣的方向和应用场景&#xff0c;然后选择相应的框架和库进行学习。 官方文档和教程&a…

Linux 学习记录56(ARM篇)

Linux 学习记录56(ARM篇) 本文目录 Linux 学习记录56(ARM篇)一、总线概念1. 总线2. 串行总线3. 并行总线4. 单工/半双工/全双工5. 同步6. 异步 二、串口(UART)1. 串口配置信息2. 串口通信协议(异步串行全双工总线)3. 框图分析4. 使能串口5. GPIO的复用模式6. RCC时钟7. UART寄存…

python的闭包

一、介绍 Python 中的闭包&#xff08;Closure&#xff09;是指一个函数对象&#xff08;称为内部函数&#xff09;捕获并引用了其所在函数&#xff08;称为外部函数&#xff09;中的变量&#xff0c;即使外部函数已经执行完毕&#xff0c;内部函数仍然可以访问和操作外部函数…

当配置Windows系统下的docker配置了阿里云镜像后下载依然很慢时多配几个镜像可以改善问题

前情介绍&#xff1a;在以前的docker版本中只需配阿里云的镜像下载就很快了&#xff0c;但是下载了新版本docker in Windows后&#xff0c;置Windows系统下的docker配置了阿里云镜像后下载依然很慢时&#xff0c;之后多配几个镜像可以改善问题。 问题现象&#xff1a; 1、下载慢…

uniapp h5 竖向的swiper内嵌视频实现抖音短视频垂直切换,丝滑切换视频效果,无限数据加载不卡顿

一、项目背景&#xff1a;实现仿抖音短视频全屏视频播放、点赞、评论、上下切换视频、视频播放暂停、分页加载、上拉加载下一页、下拉加载上一页等功能。。。 二、前言&#xff1a;博主一开始一直想实现类似抖音进入页面自动播放当前视频&#xff0c;上下滑动切换之后播放当前…

移远通信推出新一代高算力智能模组SG885G-WF,为工业和消费级IoT应用带来全新性能标杆

2023年7月24日&#xff0c;全球领先的物联网整体解决方案供应商移远通信宣布&#xff0c;正式推出其新一代旗舰级安卓智能模组SG885G-WF。该智能模组具有高达48 TOPS 的AI综合算力、强大性能及丰富的多媒体功能&#xff0c;非常适用于需要高处理能力和多媒体功能的工业和消费者…

T113-S3-RTL8822CU模块驱动移植

目录 前言 一、驱动源码获取 二、源码编译 三、驱动模块加载测试 前言 在嵌入式系统开发中&#xff0c;移植外部硬件设备的驱动是一个常见的任务。本文将分享如何在全志平台上成功移植RTL8822CU无线模块的驱动&#xff0c;以实现无线网络功能。 提示&#xff1a;以下是本篇文…

(四)RabbitMQ高级特性(消费端限流、利用限流实现不公平分发、消息存活时间、优先级队列

Lison <dreamlison163.com>, v1.0.0, 2023.06.23 RabbitMQ高级特性&#xff08;消费端限流、利用限流实现不公平分发、消息存活时间、优先级队列 文章目录 RabbitMQ高级特性&#xff08;消费端限流、利用限流实现不公平分发、消息存活时间、优先级队列消费端限流利用限流…

(一)认识InfluxDB

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 1 章 认识InfluxDB 1.1 InfluxDB的使用场景 InfluxDB是一种时序数据库&#xff0c;时序数据库通常被用在监…

MySQL笔记——表的修改查询相关的命令操作

系列文章目录 MySQL笔记——MySQL数据库介绍以及在Linux里面安装MySQL数据库&#xff0c;对MySQL数据库的简单操作&#xff0c;MySQL的外接应用程序使用说明 文章目录 系列文章目录 一 表的修改操作 1.1 修改表的名字 1.2 添加一列score 1.3 修改列名称 1.4 修改新增列的…

containerd

Containerd是一个开源的容器运行时&#xff08;Container Runtime&#xff09;&#xff0c;它是Kubernetes和Docker等容器平台的基础组件之一。它旨在提供容器的生命周期管理和基本的运行时功能&#xff0c;使得容器的创建、启动、停止、删除等操作变得简单且高效。 Container…

Apipost使用教程

Apipost是一款集API调试、生成文档、Mock、测试于一体的协同工具。单个工具可以同时满足接口测试、生成/分享文档、Mock、流程测试等功能&#xff0c;还有超实用的多人多角色间实时协作的功能。将前端、后端、测试三种角色串联起来&#xff0c;从而实现工作流程无缝衔接、提高研…

C#中简单Winform程序编译(待验证)

1、文件架构 2、MainWindow.xaml <Window x:Class"WpfApp1.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http://schemas.microsoft.…

vue中的异步请求Axios(个人学习笔记五)

目录 友情提醒第一章、传统的jQuery方式获取数据1.1&#xff09;后端controller层代码1.2&#xff09;传统的jQuery获取数据1.3&#xff09;使用vue对象和jQuery获取异步数据 第二章、使用Axios获取数据2.1&#xff09;axios简介2.2&#xff09;axios两种使用方式2.3&#xff0…

WEB:easyphp

背景知识 php弱类型比较 MD5碰撞 题目 进行代码审计 <?php highlight_file(__FILE__); $key1 0;//值赋值 $key2 0;$a $_GET[a];//get方法获取值 $b $_GET[b];if(isset($a) && intval($a) > 6000000 && strlen($a) < 3){ //a的值需要大于 60000…

Seaborn中怎样绘制双变量分布图?

两个变量的二元分布可视化也很有用。在 Seaborn中最简单的方法是使用 jointplot()函数&#xff0c;该函数可以创建一个多面板图形&#xff0c;比如散点图、二维直方图、核密度估计等&#xff0c;以显示两个变量之间的双变量关系及每个变量在单坐标轴上的单变量分布。 jointplo…

Linux--Block group

Block Group&#xff1a;ext2文件系统会根据分区的大小划分为数个Block Group。而每个Block Group都有着相 同的结构组成。政府管理各区的例子 超级块&#xff08;Super Block&#xff09;&#xff1a;存放文件系统本身的结构信息。记录的信息主要有&#xff1a;bolck 和 inod…

App测试流程及测试点

1 APP测试基本流程 1.1流程图 1.2测试周期 测试周期可按项目的开发周期来确定测试时间&#xff0c;一般测试时间为两三周&#xff08;即15个工作日&#xff09;&#xff0c;根据项目情况以及版本质量可适当缩短或延长测试时间。正式测试前先向主管确认项目排期。 1.3测试资源…

测试覆盖率 JVM 字节码测试运用 - 远程调试、测试覆盖、影子数据库

目录 前言&#xff1a; 简介 基础使用方式介绍 工具特性 前言&#xff1a; 在软件开发中&#xff0c;测试覆盖率是一个非常重要的指标&#xff0c;它表示代码中所有的测试用例是否都已经被覆盖到。JVM 字节码测试是一种比较新的测试方法&#xff0c;它可以对 JVM 字节码进…