当前位置: 首页 > 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…...

2026学生免费用AI编程神器全攻略——白嫖不要白不要,大学生快来

好的,上一章刚教你用GitHub武装自己,筑起技术护城河,但光会搬砖(敲命令)还不够,你得学会“开高达”——用AI编程助手把效率拉满。 2026年了,如果还纯靠手打for循环和查API文档,那你…...

ROS2 Humble下,如何用MoveIt! Action接口让机械臂“听话”?一个抓取demo的完整复盘

ROS2 Humble下机械臂精准控制实战:从MoveIt! Action接口到完整抓取任务 在工业自动化和服务机器人领域,机械臂的精准运动控制一直是核心挑战。ROS2 Humble版本中的MoveIt!框架为这一挑战提供了优雅的解决方案,而理解其Action接口的运作机制则…...

Cogito v1预览版3B模型实战体验:超越Llama/DeepSeek的混合推理能力

Cogito v1预览版3B模型实战体验:超越Llama/DeepSeek的混合推理能力 1. 模型概览与核心优势 1.1 什么是Cogito v1预览版 Cogito v1预览版是Deep Cogito推出的混合推理模型系列,这个3B参数的版本在多项基准测试中表现优异。与传统的语言模型不同&#x…...

造相Z-Image文生图模型v2实战应用:电商主图、课件插图、设计提案一键生成

造相Z-Image文生图模型v2实战应用:电商主图、课件插图、设计提案一键生成 1. 为什么选择Z-Image v2进行商业图像创作 在当今内容爆炸的时代,视觉素材的需求量呈指数级增长。传统图像创作方式面临三大痛点:专业设计师成本高昂、版权素材获取…...

Swiper动画进阶:手把手教你用Swiper Animate制作节日主题动画(2023最新版)

Swiper动画进阶:手把手教你用Swiper Animate制作节日主题动画(2023最新版) 当节日氛围遇上交互设计,如何让静态页面"活"起来?Swiper Animate作为Swiper生态中的动画引擎,能通过简单的类名配置实现…...

3个创新方法:用Krita AI Diffusion插件实现智能动画制作

3个创新方法:用Krita AI Diffusion插件实现智能动画制作 【免费下载链接】krita-ai-diffusion Streamlined interface for generating images with AI in Krita. Inpaint and outpaint with optional text prompt, no tweaking required. 项目地址: https://gitco…...

Gemma-3 Pixel Studio实战教程:离线模式部署与本地模型权重缓存策略

Gemma-3 Pixel Studio实战教程:离线模式部署与本地模型权重缓存策略 1. 项目概述与核心价值 Gemma-3 Pixel Studio是基于Google最新开源Gemma-3-12b-it模型构建的多模态对话终端,将强大的文本理解能力与视觉感知功能完美结合。与传统对话系统相比&…...

客服机器人开放平台能自建知识库吗?以百应Agent为例,探讨成都企业售后自动解答的实现路径

在数字化转型加速的今天,成都作为西部电商和制造业重镇,众多企业面临售后咨询量激增的挑战。退货、物流追踪、产品故障排查等售后问题占客服咨询的 60% 以上,传统人工客服成本高、响应慢,已难以满足用户即时需求。客服机器人开放平…...

科哥二次开发Image-to-Video:性能提升39%,小白友好度大增

科哥二次开发Image-to-Video:性能提升39%,小白友好度大增 1. 项目背景与核心价值 Image-to-Video技术正在改变内容创作的方式,它能够将静态图片转化为生动的视频内容。然而,原始I2VGen-XL模型在实际应用中面临两大挑战&#xff…...

3步解决macOS应用更新烦恼:开源神器Latest使用指南

3步解决macOS应用更新烦恼:开源神器Latest使用指南 【免费下载链接】Latest A small utility app for macOS that makes sure you know about all the latest updates to the apps you use. 项目地址: https://gitcode.com/gh_mirrors/la/Latest 你是否曾为m…...