Redis与数据库的一致性

Redis与数据库的数据一致性

在使用Redis作为应用缓存来提高数据的读性能时,经常会遇到Redis与数据库的数据一致性问题。简单来说,就是同一份数据同时存在于Redis和数据库,如何在数据更新的时候,保证两边数据的一致性。首先,如果期望Redis与数据库保持强一致性,则必须额外引入分布式事务组件,通过一致性协议(如2PC、3PC等)来保证缓存和数据库的一致性。这里讨论的一致性是最终一致性,即Redis中的数据将最终和数据库中的数据保持一致。

Redis缓存模式

Redis缓存模式并没有统一的范式,这里主要是借鉴本地缓存的设计模式,尝试总结出Redis的缓存模式。本地缓存在进行设计时,主要有以下几种常见的模式:cache aside,read through,write through,write around,write back。
在cache aside模式中,对于读请求,客户端应用会优先访问缓存,如果缓存命中,则直接返回数据;如果缓存未命中,则会进一步请求数据库,然后将数据写入缓存。在read through中,缓存负责保持与数据库的一致。当数据未命中时,缓存会主动从数据库中读取该未命中数据,并回写缓存,然后将这部分数据返回给客户端应用。在write through模式中,数据首先写入缓存,然后写入数据库。与read through一样,写入总是通过缓存到达数据库。在write around模式中,数据直接由客户端应用写入数据库,然后让Cache中对应数据无效。在write back模式中,客户端应用将数据写入缓存后,缓存会立即确认,并在延迟一段时间后将数据写回数据库。更多缓存设计模式相关细节可以参考笔者软件系统缓存设计一文。
以上五种缓存设计模式,cache aside模式与read through模式主要针对读请求的场景,且在第一次请求数据时,总是会导致缓存未命中,并额外带来将数据加载到缓存的操作。相比cache aside模式是客户端应用从数据库读取缓存未命中数据并将其写入缓存,read through模式是由缓存从数据库读取未命中数据并将其写入到缓存。对于Redis缓存来说,由于Redis缓存和数据库是两个独立的组件,所以Redis缓存不可能使用read through模式,而只能使用cache aside模式。
而write through模式、write around模式与write back模式主要针对写请求的场景,三种模式均需要将数据写入数据库,只是写入的主体或写入的时机不同。对于Redis缓存来说,同样由于Redis缓存和数据库是两个独立的组件,所以Redis缓存不可能使用write through模式或write back模式,而只能使用write around模式,即数据直接由客户端应用写入数据库。至此,Redis缓存的常用设计模式如下:

请添加图片描述

从上图可知,当客户端应用发起读请求时,客户端应用首先尝试从Redis中读取数据,如果缓存中命中数据,则直接从缓存读取数据。如果缓存未命中,则先从数据库读取数据,并将数据写入缓存。当客户端应用发起写请求时,客户端应用直接将新数据写入数据库。同时为保证Redis与Database的最终一致性,在客户端应用将数据写入缓存时,设置一个TTL,避免脏数据一直保存在Redis中。上述过程的伪代码表示如下:

Object readData(String keyStr) {
    Object data = readRedis(keyStr);
    if (data != null) {
        return data;
    }
    data = readDatabase(keyStr);
    writeRedis(keyStr, data, ttl);
    return data;
}

boolean writeData(String keyStr, Object data) {
    return writeDatabase(keyStr, data);
}

针对写请求场景(新数据写入、已有数据的更新、已有数据的删除),特别是已有数据的更新和已有数据的删除这种情况,因为对于上述模式来说,只是将数据写入数据库,会带来Redis和数据的不一致。因为向Redis写入数据时,设置了TTL,所以一段时间后,Redis中的数据将最终与数据库一致。

总结

如果期望实现Redis缓存中数据与数据库中数据的强一致性,那么需要额外引入分布式事务组件,通过一致性协议(2PC、3PC)来实现实现Redis缓存中数据与数据库中数据的强一致性。但是,分布式事务组件的引入无疑会降低Redis缓存加速查询的初衷。所以很少看到需要Redis缓存中数据与数据库中数据保持强一致性的情况。
既然不强制要求Redis缓存中数据与数据库中数据的强一致性,那么是否可以加快Redis中数据与数据库中数据一致性的收敛速度呢?网络上针对如何加快Redis中数据与数据库中数据一致性的收敛速度,提出了多种解决方案,如:先更新数据库,再更新Redis;先更新数据库,再删除Redis中数据(直接删除Redis、延迟删除Redis);先删除Redis中数据,再更新数据库;先尝试删除Redis中数据,再更新数据库,再尝试删除Redis中数据(双删策略);先写数据库,然后通过binlog或队列,异步更新Redis中数据。笔者认为,以上方案虽然自成一体,但是不免纸上谈兵、画蛇添足,存在过度设计的问题。以上方案的一个公共特征是为了加快Redis中数据与数据库中数据一致性的收敛速度,需要执行多余的Redis写入步骤或引入额外的功能或组件(如数据库的binlog日志、队列等)。且在提升设计复杂度的同时,并没有真正起到加速一致性收敛的效果或收效甚微。且额外的Redis写入操作会加大Redis主从结点间同步负担,带来更多问题。
笔者认为,使用Redis作为缓存,就是已经接受了Redis缓存中数据可能存在脏数据的情况,且用户对数据不一致性的时间可容忍。与其考虑如何加快一致性收敛的速度,倒不如从业务出发,考虑Redis缓存的使用姿势是否合理,如将一些频繁更新且用户敏感的数据保存到Redis缓存就是一种不合理的使用;将数据长期的存储在Redis缓存中,且设置过长的TTL就是将Redis当做数据库使用,而不是缓存。此外,还应考虑将缓存前置,尝试使用客户端应用的本地缓存来提升性能。

参考

https://mp.weixin.qq.com/s/az1D1lKcoU9hiOIJjmjlJQ 4 种策略让 MySQL 和 Redis 数据保持一致
https://mp.weixin.qq.com/s/RL4Bt_UkNcnsBGL_9w37Zg 如何保障 MySQL 和 Redis 的数据一致性?

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

用Blender给MetaHuman不同胖瘦身体模型做插值,计算过度模型

用Blender给MetaHuman不同胖瘦身体模型做插值,计算过度模型 本篇文章所有想法和代码均为ChatGPT所写 需求:MetaHuman的身体有瘦、标准、胖三个体型,想要通过三个体型插值计算出符合用户体型的更多模型 建议:chatGPT建议用Blender&…

Mysql数据库:主从复制与读写分离

目录 前言 一、Mysql主从复制概述 1、Mysql主从复制概念 2、Mysql主从复制功能和使用场景 2.1 功能(为何使用主从复制) 2.2 适用场景(何时使用主从复制) 3、Mysql复制的类型 3.1 基于SQL语句的复制(Statement默…

【原生小程序-增加友盟统计】

1.project.config.json中 //最外面的 {"packNpmManually": true,"packNpmRelationList": [{"packageJsonPath": "./package.json","miniprogramNpmDistDir": "./"}] }2.在终端中输入npm init -y 3.再输入命令np…

整理git上的模板框架

vite-vue3.0-ts-pinia-uni-app 技术栈的app框架 功能:基于 uni-app,一端发布多端通用,目前已经适配 H5、微信小程序、QQ小程序、Ios App、Android App。 taro3vue3tsnutuipinia taro3 框架小程序跨端平台 vue3.0-element-vite-qiankun 后台…

HarmonyOS实战开发-如何构建多种样式弹窗

介绍 本篇Codelab将介绍如何使用弹窗功能,实现四种类型弹窗。分别是:警告弹窗、自定义弹窗、日期滑动选择器弹窗、文本滑动选择器弹窗。需要完成以下功能: 点击左上角返回按钮展示警告弹窗。点击出生日期展示日期滑动选择器弹窗。点击性别展…

【动态规划】Leetcode 62. 不同路径I 63. 不同路径II

【动态规划】Leetcode 62. 不同路径I 63. 不同路径II Leetcode 62. 不同路径ILeetcode 63. 不同路径II ---------------🎈🎈62. 不同路径I 题目链接🎈🎈------------------- ---------------🎈🎈63. 不同路…

【YOLOv5改进系列(7)】高效涨点----使用yolov8中的C2F模块替换yolov5中的C3模块

文章目录 🚀🚀🚀前言一、1️⃣ C3模块和C2F模块详解1.1 🎓 C3模块1.2 ✨BottleNeck模块1.3 ⭐️C2F模块 二、2️⃣添加C2f和C2F_Bottleneck模块代码三、3️⃣新建yolov5s_C2F.yaml文件四、4️⃣修改yolo.py中的parse_model函数五…

Collction的三种遍历

目录 集合体系结构 迭代器遍历: 增强for遍历: Lambda表达式遍历 集合体系结构 List 系列集合 : 添加元素是有序的、可重复的,有索引的; 有序的:存和取的顺序是一样的; Set 系列集合 &#…

综合实验1

一、配置IP地址 [AR1]int g0/0/0 [AR1-GigabitEthernet0/0/0]ip add 192.168.1.254 24 [AR1-GigabitEthernet0/0/0]int se4/0/0 [AR1-Serial4/0/0]ip add 15.1.1.1 24 [AR1-Serial4/0/0] [AR2]int g0/0/0 [AR2-GigabitEthernet0/0/0]ip add 192.168.2.254 24 [AR2-Giga…

Sui与Revolut合作,加速Sui区块链教育和采用

作为全球一体化金融平台,Revolut与Sui合作推出了最新的加密货币学习课程。Revolut拥有全球超过4,000万用户,提供一系列数字银行产品和服务,包括购买和出售加密货币,其中包括SUI。 Revolut的学习计划为其用户提供有关Sui的教育&am…

蓝桥杯嵌入式学习笔记(7):ADC程序设计

目录 前言 1. ADC原理 1.1 主要特性 1.2 模拟输出电路图 2. 使用CubeMX进行源工程的配置 2.1 引脚配置 2.2 配置AD1 2.3 配置AD2 2.4 配置时钟 3. 代码编程 3.1 预备工作 3.2 bsp_adc.h文件编写 3.3 bsp_adc.c文件编写 3.4 main.c编写 3.4.1 时钟函数配置 3…

java子集(力扣Leetcode78)

子集 力扣原题链接 问题描述 给定一个整数数组 nums,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。解集不能包含重复的子集。可以按任意顺序返回解集。 示例 示例 1: 输入:nums [1,2,3] 输出&#x…

python3将exe 转支持库错误 AssertionError: None does not smell like code

exe -> pyc包(*.exe_extracted) 安装反编译工具 exe反编译工具:pyinstxtractor.py下载:https://sourceforge.net/projects/pyinstallerextractor/ python pyinstxtractor.py hello.exe包反编译 懒的写!!! 这有详…

英语广场期刊投稿发表论文

《英语广场》是由国家新闻出版总署批准的正规期刊,杂志本着“轻松读原作,快乐学英语”的宗旨,倡导“寓学于乐”的学习理念,其活泼的办刊风格和优秀的文章选材受到读者特别是广大中学生的广泛欢迎,取得了良好的社会效益…

redis 的设计与实现(三)——对象

1. 前言: 在第一章节我们了解到了,redis底层所涉及的数据结构,但是这并非是离我们最近的一层,在此之上,redis实现了一层对象与我们交互。我们在本篇内容中将了解到: 对象对应的实现redis一些常用特性的实现…

数字化坚鹏:小熊电器面向数字化转型的大数据顶层设计实践培训

小熊电器面向数字化转型的大数据顶层设计实践培训圆满结束 ——努力打造“数据技术营销”三轮驱动的数字化领先企业 小熊电器股份有限公司由李一峰创立于2006年,是一家专业从事创意小家电研发、设计、生产和销售的实业型企业。2019年8月23日正式在深交所挂牌上市。…

rust使用Command库调用cmd命令或者shell命令,并支持多个参数和指定文件夹目录

想要在不同的平台上运行flutter doctor命令,就需要知道对应的平台是windows还是linux,如果是windows就需要调用cmd命令,如果是linux平台,就需要调用sh命令,所以可以通过cfg!实现不同平台的判断,然后调用不同…

【21-40】操作系统基础知识(非常详细)从零基础入门到精通,看完这一篇就够了

【21-40】操作系统基础知识(非常详细)从零基础入门到精通,看完这一篇就够了 以下是本文参考的资料 欢迎大家查收原版 本版本仅作个人笔记使用44、程序从堆中动态分配内存时,虚拟内存上怎么操作的45、常见的几种磁盘调度算法1. 先来…

codesys通过moudbus TCP连接西门子1214c,西门子做客户端

思路在codesys中发送数据到西门子,西门子原封不动的将数据传回。 1.首先配置codesys; 我设置了500个,但是好像发不这么多,只能120多个。因为什么来我忘了。但是这里不影响。 2.配置映射: 3.写代码 PROGRAM PLC_PRG VARarySendDa…

URL编码:原理、应用与安全性

title: URL编码:原理、应用与安全性 date: 2024/3/29 18:32:42 updated: 2024/3/29 18:32:42 tags: URL编码百分号编码特殊字符处理网络安全应用场景标准演变未来发展 在网络世界中,URL(统一资源定位符)是我们访问网页、发送请求…