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

实战Redis与MySQL双写一致性的缓存模式

​Redis和MySQL都是常用的数据存储系统,它们各自有自己的优缺点。在实际应用中,我们可能需要将它们结合起来使用,比如将Redis作为缓存,MySQL作为持久化存储。

在这种情况下,我们需要保证Redis和MySQL的数据一致性,也就是当数据在Redis中进行修改时,也要相应地在MySQL中进行修改,反之亦然。


Cache-Aside Pattern

Cache-Aside Pattern(也称为 Lazy-Loading 缓存模式)是一种常见的缓存设计模式,用于在应用程序中手动管理缓存数据。在这种模式下,应用程序负责在需要的时候将数据加载到缓存中,以便提高数据的访问速度和性能。

Cache-Aside 模式的工作流程如下:

1. 读取数据

当应用程序需要读取数据时,它首先会检查缓存中是否存在所需数据。如果数据存在于缓存中,应用程序直接从缓存中获取数据。如果数据不在缓存中,应用程序会从主数据源(如数据库)中获取数据,并将数据加载到缓存中。

2. 写入数据

当应用程序执行写操作(如创建、更新、删除)时,它首先会更新主数据源中的数据。然后,应用程序手动更新或使缓存中的相关数据失效,以确保缓存中的数据保持与主数据源一致。

3. 缓存失效

在 Cache-Aside 模式中,缓存失效是由应用程序来管理的。这意味着应用程序需要根据数据的更新频率和业务需求,手动决定何时使缓存数据失效,以便在下次访问时重新加载最新的数据。

4.代码示例

基于Spring Cloud的Cache-Aside Pattern缓存模式可以通过Spring框架的缓存抽象和Spring Cloud的服务组件来实现。在这种模式下,应用程序负责手动地管理缓存数据的加载和失效。以下是一个基于Spring Cloud的Cache-Aside Pattern缓存模式的伪代码示例:

  • 定义缓存配置和服务

首先,需要定义一个缓存配置类和一个缓存服务类来管理缓存和数据读写操作。

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic CacheManager cacheManager() {return new ConcurrentMapCacheManager("myCache"); // 创建一个名为 "myCache" 的缓存}
}@Service
public class CacheService {private final Cache cache;public CacheService(CacheManager cacheManager) {this.cache = cacheManager.getCache("myCache"); // 获取名为 "myCache" 的缓存}public Object getDataFromCache(String key) {Cache.ValueWrapper valueWrapper = cache.get(key);if (valueWrapper != null) {return valueWrapper.get();}return null;}public void putDataInCache(String key, Object data) {cache.put(key, data); // 将数据加载到缓存中}public void invalidateCache(String key) {cache.evict(key); // 使缓存中的数据失效}
}
  • 使用缓存服务

业务逻辑中,可以使用缓存服务来读取和写入数据。

@Service
public class BusinessService {private final DataService dataService;private final CacheService cacheService;@Autowiredpublic BusinessService(DataService dataService, CacheService cacheService) {this.dataService = dataService;this.cacheService = cacheService;}public Object fetchData(String key) {Object cachedData = cacheService.getDataFromCache(key);if (cachedData != null) {return cachedData;} else {Object newData = dataService.fetchDataFromDataSource(key);cacheService.putDataInCache(key, newData);return newData;}}public void updateData(String key, Object newData) {dataService.updateDataSource(key, newData); // 更新主数据源cacheService.invalidateCache(key); // 使缓存中的数据失效}
}
  • 使用示例:

可以通过业务服务来读取和更新数据。

@RestController
public class MyController {private final BusinessService businessService;@Autowiredpublic MyController(BusinessService businessService) {this.businessService = businessService;}@GetMapping("/data/{key}")public Object getData(@PathVariable String key) {return businessService.fetchData(key); // 从缓存或数据源获取数据}@PostMapping("/data/{key}")public void updateData(@PathVariable String key, @RequestBody Object newData) {businessService.updateData(key, newData); // 更新数据并使缓存失效}
}

在这个示例中,我们使用了Spring框架的缓存注解和缓存管理器来实现Cache-Aside Pattern。通过CacheService来操作缓存数据的读写,通过BusinessService来处理业务逻辑,保证从缓存读取数据或将数据加载到缓存时的一致性。


Read-Through/Write through

Read-Through和Write-Through是两种常见的缓存模式,用于更有效地管理缓存中的数据读取和写入操作。它们分别用于在数据被读取和写入时自动操作缓存和主数据源。下面我将详细介绍这两种缓存模式,并提供基于Spring的伪代码示例。

Read-Through缓存模式

在Read-Through缓存模式中,当应用程序尝试读取缓存中的数据时,如果缓存中不存在该数据,会自动从主数据源(如数据库)中读取数据,并将数据加载到缓存中,以便下次读取时能够直接从缓存中获取。

工作流程:

  1. 应用程序尝试从缓存读取数据。

  2. 如果缓存中存在数据,应用程序直接从缓存中获取。

  3. 如果缓存中不存在数据,应用程序从主数据源中读取数据,并将数据加载到缓存中。

Write-Through缓存模式

在Write-Through缓存模式中,当应用程序执行写操作时,数据会首先被写入缓存,然后自动同步更新到主数据源(如数据库)中,以保持数据的一致性。

工作流程:

  1. 应用程序执行写操作,将数据写入缓存。

  2. 缓存自动将写入的数据同步更新到主数据源中。

代码示例

基于Spring Cloud的Read-Through和Write-Through缓存模式可以通过Spring框架的缓存抽象和Spring Cloud的服务组件来实现。这两种模式是更为自动化的缓存管理方法,它们分别处理数据的读取和写入操作,无需应用程序手动介入。以下是基于Spring Cloud的伪代码示例:

Read-Through缓存模式示例

  • 定义缓存配置和服务:

首先,需要定义一个缓存配置类和一个数据服务类,用于管理缓存和数据读取操作。

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic CacheManager cacheManager() {return new ConcurrentMapCacheManager("myCache"); // 创建一个名为 "myCache" 的缓存}
}@Service
public class DataService {@Autowiredprivate DataRepository dataRepository; // 假设有一个数据仓库@Cacheable(value = "myCache", key = "#key")public Data getData(String key) {return dataRepository.findById(key).orElse(null);}
}
  • 使用缓存服务:

在业务逻辑中,可以使用缓存服务来读取数据。

@RestController
public class MyController {private final DataService dataService;@Autowiredpublic MyController(DataService dataService) {this.dataService = dataService;}@GetMapping("/data/{key}")public Data getData(@PathVariable String key) {return dataService.getData(key); // 从缓存或数据仓库获取数据}
}

Write-Through缓存模式示例

  • 定义缓存配置和服务:

同样,你需要定义一个缓存配置类和一个数据服务类,用于管理缓存和数据写入操作。

@Configuration
@EnableCaching
public class CacheConfig {@Beanpublic CacheManager cacheManager() {return new ConcurrentMapCacheManager("myCache"); // 创建一个名为 "myCache" 的缓存}
}@Service
public class DataService {@Autowiredprivate DataRepository dataRepository; // 假设有一个数据仓库@CachePut(value = "myCache", key = "#data.key")public Data updateData(Data data) {dataRepository.save(data); // 更新数据到数据仓库return data;}
}
  • 使用缓存服务:

可以使用缓存服务来写入数据。

@RestController
public class MyController {private final DataService dataService;@Autowiredpublic MyController(DataService dataService) {this.dataService = dataService;}@PostMapping("/data")public Data updateData(@RequestBody Data newData) {return dataService.updateData(newData); // 写入数据到缓存和数据仓库}
}

在这些示例中,@Cacheable@CachePut注解用于实现Read-Through和Write-Through缓存模式。DataService类负责在数据读取和写入时处理缓存和主数据源之间的同步。


Write behind

Write-Behind缓存模式是一种缓存设计模式,它将写入操作先缓存起来,然后在合适的时机异步地将数据写入主数据源(例如数据库)。这种模式可以提高写入操作的性能和响应时间,同时通过异步写入减少主数据源的负载。

工作原理

  1. 当应用程序执行写入操作时,数据首先会被写入缓存,然后标记为"脏数据"。
  2. 后台异步线程定期或在特定事件触发时,将"脏数据"批量写入主数据源。

这种模式在需要频繁写入操作的场景中特别有用,因为它将写入操作进行了批处理,减少了与主数据源的交互次数,从而提高了性能。

Write-Behind缓存模式的优点

  • 提高写入操作的性能:写入操作首先在缓存中完成,减少了对主数据源的直接写入次数,从而提高了写入性能。
  • 减轻主数据源负载:异步写入减少了主数据源的负载,特别是在高并发的情况下。
  • 高吞吐量:通过批量写入的方式,可以提高系统的吞吐量。

代码示例

基于Spring Cloud的Write-Behind缓存模式可以使用Spring框架的缓存抽象和Spring Cloud的服务组件来实现。这种模式可以提高写入操作的性能和响应时间,同时通过异步写入减少主数据源的负载。以下是基于Spring Cloud的Write-Behind缓存模式的伪代码示例:

  • 定义缓存配置和服务:

首先,需要定义一个缓存配置类和一个缓存服务类,用于管理缓存和数据写入操作。

import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@Configuration
@EnableCaching
@EnableAsync
public class CacheConfig {@Beanpublic CacheManager cacheManager() {return new ConcurrentMapCacheManager("myCache"); // 创建一个名为 "myCache" 的缓存}@Beanpublic ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(5);executor.setMaxPoolSize(10);executor.setQueueCapacity(25);return executor;}
}@Service
public class CacheService {@Autowiredprivate DataRepository dataRepository;@CachePut(value = "myCache", key = "#data.key")@Asyncpublic void writeBehind(Data data) {// 异步将数据写入主数据源writeDataToDataSource(data);}private void writeDataToDataSource(Data data) {dataRepository.save(data); // 写入数据到主数据源}
}
  • 使用缓存服务:

在业务逻辑中,可以使用缓存服务来写入数据。

@RestController
public class MyController {private final CacheService cacheService;@Autowiredpublic MyController(CacheService cacheService) {this.cacheService = cacheService;}@PostMapping("/data")public void writeData(@RequestBody Data newData) {cacheService.writeBehind(newData); // 异步写入数据到缓存和主数据源}
}

在这个示例中,我们使用了Spring框架的@CachePut注解和异步任务来实现Write-Behind缓存模式。CacheService负责在数据写入缓存的同时,异步地将数据写入主数据源。这样可以提高写入性能,并减轻主数据源的负载。

相关文章:

实战Redis与MySQL双写一致性的缓存模式

​Redis和MySQL都是常用的数据存储系统,它们各自有自己的优缺点。在实际应用中,我们可能需要将它们结合起来使用,比如将Redis作为缓存,MySQL作为持久化存储。 在这种情况下,我们需要保证Redis和MySQL的数据一致性&…...

KVM环境下制作ubuntu qcow2格式镜像

如果是Ubuntu KVM环境是VMware虚拟机,需要CPU开启虚拟化 1、配置镜像源 wget -O /etc/apt/sources.list https://www.qingtongqing.cc/ubuntu/sources.list2、安装kvm qemu-img libvirt kvm虚拟化所需环境组件 apt -y install qemu-kvm virt-manager libvirt-da…...

基于SpringBoot+Vue的高校竞赛管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…...

PHP发邮件教程:配置SMTP服务器发送邮件?

PHP发邮件的几种方式?如何使用PHP通过SMTP协议发信? PHP作为一种广泛使用的服务器端脚本语言,提供了多种方式来发送邮件。AokSend将详细介绍如何通过配置SMTP服务器来实现PHP发邮件教程的核心内容。 PHP发邮件教程:设置参数 这…...

SpringBootWeb增删改查入门案例

前言 为了快速入门一个SpringBootWeb项目,这里就将基础的增删改查的案例进行总结,作为对SpringBootMybatis的基础用法的一个巩固。 准备工作 需求说明 对员工表进行增删改查操作环境搭建 准备数据表 -- 员工管理(带约束) create table emp (id int …...

pytorch实现RNN网络

目录 1.导包 2. 加载本地文本数据 3.构建循环神经网络层 4.初始化隐藏状态state 5.创建随机的数据,检测一下代码是否能正常运行 6. 构建一个完整的循环神经网络 7.模型训练 8.个人知识点理解 1.导包 import torch from torch import nn from torch.nn imp…...

智能工厂的软件设计 “程序program”表达式,即 接口模型的代理模式表达式

Q1、前面将“智能工厂的软件设计”中绝无仅有的“程序”视为 专注于 给定的某个单一面(语言面/逻辑面/数学面)中的 问题,专注于分析问题和解决问题的程序活动的组织,每一面都是一个“组织者”就像一个“独角兽”,并提出…...

leetcode 难度【简单模式】标签【数据库】题型整理大全

文章目录 175. 组合两个表181. 超过经理收入的员工182. 查找重复的电子邮箱COUNT(*)COUNT(*) 与 COUNT(column) 的区别 where和vaing之间的区别用法 183.从不订购的客户196.删除重复的电子邮箱197.上升的温度511.游戏玩法分析I512.游戏玩法分析II577.员工奖金584.寻找用户推荐人…...

利士策分享,自我和解:通往赚钱与内心富足的和谐之道

利士策分享,自我和解:通往赚钱与内心富足的和谐之道 在这个快节奏、高压力的时代,我们往往在追求物质财富的同时,忽略了内心世界的和谐与平衡。 赚钱,作为现代生活中不可或缺的一部分,它不仅仅是生存的手段…...

【物联网】深入解析时序数据库TDengine及其Java应用实践

文章目录 一、什么是时序数据库?二、TDengine简介三、TDengine的Java应用实践(1)环境准备(2)数据插入(3)数据查询 一、什么是时序数据库? 时序数据库(Time-Series Datab…...

2023北华大学程序设计新生赛部分题解

时光如流水般逝去,我已在校园中奋战大二!(≧▽≦) 今天,静静回顾去年的新生赛,心中涌起无尽感慨,仿佛那段青春岁月如烟花般绚烂。✧。(≧▽≦)。✧ 青春就像一场燃烧的盛宴,激情澎湃&…...

PPP的配置

概述:PPP模式,即公私合作模式(Public-Private Partnership),是一种公共部门与私营部门合作的模式。 一、实验拓扑 实验一:PPP基本功能 实验步骤: (1)配置AR1的接口IP地…...

回溯算法总结篇

组合问题:N个数里面按一定规则找出k个数的集合 如果题目要求的是组合的具体信息,则只能使用回溯算法,如果题目只是要求组合的某些最值,个数等信息,则使用动态规划(比如求组合中元素最少的组合,…...

机器学习-点击率预估-论文速读-20240916

1. [经典文章] 特征交叉: Factorization Machines, ICDM, 2010 分解机(Factorization Machines) 摘要 本文介绍了一种新的模型类——分解机(FM),它结合了支持向量机(SVM)和分解模型的优点。与…...

【leetcode】堆习题

215.数组中的第K个最大元素 给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。 你必须设计并实现时间复杂度为 O(n) 的算法解决此问题。 示例 1: 输…...

前端大模型入门:编码(Tokenizer)和嵌入(Embedding)解析 - llm的输入

LLM的核心是通过对语言进行建模来生成自然语言输出或理解输入,两个重要的概念在其中发挥关键作用:Tokenizer 和 Embedding。本篇文章将对这两个概念进行入门级介绍,并提供了针对前端的js示例代码,帮助读者理解它们的基本原理/作用和如何使用。 1. 什么是…...

一文读懂 JS 中的 Map 结构

你好,我是沐爸,欢迎点赞、收藏、评论和关注。 上次聊了 Set 数据结构,今天我们聊下 Map,看看它与 Set、与普通对象有什么区别?下面直接进入正题。 一、Set 和 Map 有什么区别? Set 是一个集合&#xff0…...

C++校招面经(二)

欢迎关注 0voice GitHub 6、 C 和 Java 区别(语⾔特性,垃圾回收,应⽤场景等) 指针: Java 语⾔让程序员没法找到指针来直接访问内存,没有指针的概念,并有内存的⾃动管理功能,从⽽…...

Python Web 面试题

1 Web 相关 get 和 post 区别 get: 请求数据在 URL 末尾,URL 长度有限制 请求幂等,即无论请求多少次,服务器响应始终相同,这是因为 get 至少获取资源,而不修改资源 可以被浏览器缓存,以便以后…...

java日志框架之JUL(Logging)

文章目录 一、JUL简介1、JUL组件介绍 二、Logger快速入门三、Logger日志级别1、日志级别2、默认级别info3、原理分析4、自定义日志级别5、日志持久化(保存到磁盘) 三、Logger父子关系四、Logger配置文件 一、JUL简介 JUL全程Java Util Logging&#xff…...

为什么软件开发偏爱 Linux?深度剖析 Linux 相较于 Windows 的核心优势

引言 在软件开发的世界里,一个有趣的现象是:无论是大型互联网公司的服务器集群,还是资深程序员的个人开发机,Linux 操作系统的身影无处不在。与之形成鲜明对比的是,尽管 Windows 在个人消费市场占据绝对主导地位&…...

【紧急预警】Lindy衰减临界点已提前至第8.3个月!2024最新《营销自动化寿命健康度白皮书》限时开放前500份

更多请点击: https://kaifayun.com 第一章:Lindy衰减临界点的理论重构与实证突破 Lindy效应传统上描述“越老越长寿”的非线性生存规律,但其在现代软件系统、开源生态与协议层技术栈中的适用边界正遭遇结构性挑战。本文首次将Lindy模型从静…...

Unity渲染排序三要素:SortingLayer、Order in Layer与RenderQueue协同原理

1. 为什么刚进Unity的美术和程序总在“图层遮挡”上反复拉扯?“这个UI怎么被背景挡住了?”“粒子特效一开就穿模,明明Z轴没问题!”“我调了Order in Layer到999,还是被另一个Sprite挡住——它连Sorting Layer都没改过&…...

AI IDE 革命:程序员正在被重新定义

很多开发者第一次使用 Cursor 的 CtrlK 或 Composer(高级多文件编辑模式)时,都会有一种强烈的、甚至让人有些脊背发凉的冲击感。 因为: 它已经不再是那个我们熟悉的、只能在原地等待光标落下的: “代码自动补全插件&am…...

告别SVN恐惧症:美术策划也能轻松上手的Unity PlasticSCM极简入门(附团队项目拉取实战)

告别SVN恐惧症:美术策划也能轻松上手的Unity PlasticSCM极简入门(附团队项目拉取实战) 在游戏开发团队中,版本控制系统是协作的基石,但传统工具如SVN往往让非技术成员望而生畏。当美术资源频繁更新、策划案不断迭代时&…...

告别杂乱!用FileMenu Tools 8.4.2一键清理Windows 11右键菜单(附隐藏技巧)

Windows 11右键菜单精简指南:用FileMenu Tools打造高效工作流每次在文件上点击右键时,那个缓慢弹出的冗长菜单是否让你感到烦躁?随着安装的软件越来越多,Windows的右键菜单往往会变得臃肿不堪,严重影响工作效率。今天&…...

DLA功耗优化验证:tegrastats实战指南

重磅预告:本专栏将独家连载系列丛书《智能体视觉技术与应用》部分精华内容,该书是世界首套系统阐述“因式智能体”视觉理论与实践的专著,特邀美国 TypeOne 公司首席科学家、斯坦福大学博士 Bohan 担任技术顾问。Bohan先生师从美国三院院士、“…...

5步彻底解决Windows DLL加载冲突:UE4SS系统故障排查指南

5步彻底解决Windows DLL加载冲突:UE4SS系统故障排查指南 【免费下载链接】RE-UE4SS Injectable LUA scripting system, SDK generator, live property editor and other dumping utilities for UE4/5 games 项目地址: https://gitcode.com/gh_mirrors/re/RE-UE4SS…...

qobuz-dl终极实战指南:专业无损音乐下载工具架构解析与高效应用

qobuz-dl终极实战指南:专业无损音乐下载工具架构解析与高效应用 【免费下载链接】qobuz-dl A complete Lossless and Hi-Res music downloader for Qobuz 项目地址: https://gitcode.com/gh_mirrors/qo/qobuz-dl 在数字音乐时代,追求极致音质的音…...

基于CNN的食双星光变曲线自动化参数初估模型EBOP MAVEN

1. 项目概述与核心价值在恒星天体物理领域,食双星系统一直扮演着“宇宙实验室”的关键角色。通过分析两颗恒星相互绕转时周期性相互遮挡产生的光变曲线,我们可以像解谜一样,精确反演出恒星的质量、半径、轨道倾角等基本物理参数。这些参数是构…...