论坛
潜水/灌水快乐,沉淀知识,认识更多同行。
ToB圈子
加入IT圈,遇到更多同好之人。
朋友圈
看朋友圈动态,了解ToB世界。
ToB门户
了解全球最新的ToB事件
博客
Blog
排行榜
Ranklist
文库
业界最专业的IT文库,上传资料也可以赚钱
下载
分享
Share
导读
Guide
相册
Album
记录
Doing
搜索
本版
文章
帖子
ToB圈子
用户
免费入驻
产品入驻
解决方案入驻
公司入驻
案例入驻
登录
·
注册
只需一步,快速开始
账号登录
立即注册
找回密码
用户名
Email
自动登录
找回密码
密码
登录
立即注册
首页
找靠谱产品
找解决方案
找靠谱公司
找案例
找对的人
专家智库
悬赏任务
圈子
SAAS
IT评测·应用市场-qidao123.com
»
论坛
›
数据库
›
向量数据库
›
一文彻底搞懂 Redis 缓存与数据库一致性
一文彻底搞懂 Redis 缓存与数据库一致性
天津储鑫盛钢材现货供应商
论坛元老
|
2024-8-5 15:50:25
|
显示全部楼层
|
阅读模式
楼主
主题
1012
|
帖子
1012
|
积分
3036
1. 一致性问题
存储如mysql通常支持完备的ACID特性,因为可靠性,长期性等因素,性能普遍不高,高并发的查询会给mysql带来压力,造成数据库系统的不稳固。同时也轻易产生耽误。根据局部性原理,80%请求会落到20%的热点数据上,在读多写少场景,增加一层缓存非常有助提升系统吞吐量和健壮性。
一样平常的业务场景都是读多写少的,当客户端的请求太多,对数据库的压力越来越大,引入缓存来降低数据库的压力是必然选择,目前业内主流的选择基本是利用 Redis 作为数据库的缓存。但是引入缓存以后,对我们系统的设计带来了很大的挑战,其中缓存和数据库的数据一致性问题就是一个非常棘手的问题。
当数据库的数据发生变化的时间,引入 Redis 缓存以后,增加了数据操纵难度,既要操纵数据库又要操纵 Redis,对 Redis和数据库的操纵有 2 种方案:
1、先操纵 Redis,再操纵数据库
2、先操纵数据库,再操纵 Redis
我们无论选择以上的哪个方案,都希望数据操纵要么都乐成,要么都失败,我们不希望看到一个失败,一个乐成的结果,因为这样就产生了数据不一致的问题。
2. 针对读场景
如果redis中存在用户所需数据,直接返回即可;如果不存在,则试图从db中读取数据,读取完成后,将该数据更新到redis中,避免下次再次查询或其他用户查询时,仍从db读取。
在高并发场景下,两次请求同时请求redis,发现数据并不存在后,都会从db中加载数据,然后再重新将数据写入redis,无论两次请求的写操纵谁先谁后,数据本身是一样的,只不过额外举行了一次数据写覆盖。因此不会产生数据不一致的问题。
3. 针对写场景
如果redis中本身不存在缓存数据,则直接修改db中的数据即可,不会产生数据不一致问题。
如果redis中已存在缓存数据,则需要同时修改db和redis中的数据,但是二者修改操纵的执行必然存在先后次序。在高并发的场景下,就有大概产生数据不一致的情况。
那么针对此中数据不一致问题,就产生了以下两个疑问:
问题1、由于redis中的数据可有可无,那么当数据发生变化时,是对redis中的数据举行修改,照旧直接删除对应的redis,然后通过后续的读请求再回源db,将数据重新写入redis呢?
问题2、redis和db的数据写操纵的次序问题,是先更新redis,照旧先更新db?
4. 解决方案
4.1 问题1:缓存淘汰战略或缓存更新战略
方案1: 淘汰缓存战略
长处:操纵简单,直接将对应缓存删除即可
缺点:由于缓存被删除后,下次的读请求无法掷中缓存,需回源db,将数据重新写入redis
方案2: 更新缓存战略
长处:缓存掷中率高,只要缓存举行了更新,后续的读请求不会出现缓存未掷中(cache miss)的情况
缺点:在某些业务场景下,缓存更新的成本过大。且更新后的缓存不一定会被利用。
综合分析
实在业界一样平常接纳的都是缓存淘汰战略,而非缓存更新战略。缘故起因有三:
大多数情况下,redis缓存中的数据并不是完全copy db中的数据,而是将db中多张表的数据举行了重新盘算,筛选后更新到redis。如果在db某一张表的数据发生了变化的情况下,需要同步重新盘算redis中的值,成本过高。
缓存更新后的新值,无法包管一定会有读请求掷中,如果不停没有请求掷中该部门冷数据,实在是产生了一定的资源浪费(盘算成本+存储成本)。
相较于淘汰缓存战略中,仅有一次读请求cache miss的结果来说,淘汰缓存战略的缺点完全可以容忍。
举个例子来说,a表中的字段,1分钟更改了100次,如果接纳更新缓存战略,则需要盘算100次,哪怕1分钟内只有1次读请求;如果接纳淘汰缓存战略,如果1分钟内只有1次请求,则只需要盘算1次即可,开销大幅度降低。
4.2 问题2:redis和db写操纵,谁先谁后?
注意:以下的方案讨论都是基于redis淘汰缓存操纵以及数据库更新操纵包管乐成(可通过重试机制解决)的情况下,高并发的业务场景中的解决方案。
方案1,先淘汰缓存,后更新数据库的战略,有大概导致长时间的数据不一致问题,可以通过延时双删 or 异步更新缓存战略举行解决。
方案2,先更新数据库,后更新缓存,有大概导致极短时间内的数据不一致,但是数据终极是一致的。
方案1: 先淘汰缓存,后更新数据库
正常情况
A请求举行写操纵,先淘汰缓存,再更新数据库
B请求举行读操纵,由于A请求已将缓存淘汰,B请求没有在redis中发现所需数据,因此从数据库中读取数据,并更新缓存到redis中
异常情况1
A请求举行写操纵,先淘汰缓存
B请求举行读操纵,由于A请求已将缓存淘汰,B请求没有在redis中发现所需数据,因此从数据库中读取数据,并更新缓存到redis中。注意,此时redis中被更新的依然是老数据,A请求的数据库更新操纵尚未完成
A请求举行数据库更新操纵。此时,数据库中是新数据,redis缓存中是老数据,产生了数据不一致的问题。且该不一致会不停持续到缓存自然失效或者下次的更新操纵
对于该种异常情况,提供两种解决思绪:
异步更新缓存。
A请求举行写操纵,先淘汰缓存
B请求举行读操纵,由于A请求已将缓存淘汰,B请求没有在redis中发现所需数据,因此从数据库中读取数据。注意,此时不向redis写入新的缓存战略
A请求通过订阅数据库binlog,对redis缓存数据举行异步更新
该方案虽然解决了数据不一致的问题,但是在数据库更新操纵完成前,所有的读请求都会直接打到数据库上,具有比较大的风险。
延时双删。
A请求举行写操纵,先淘汰缓存
B请求举行读操纵,由于A请求已将缓存淘汰,B请求没有在redis中发现所需数据,因此从数据库中读取数据,并更新缓存到redis中。注意,此时redis中被更新的依然是老数据,A请求的数据库更新操纵尚未完成。假设该步骤耗时N秒
A请求举行数据库更新操纵。
由于此时redis中写入了老数据,因此A请求在休眠M秒后(M略大于N),再次对redis举行淘汰缓存操纵
该方案虽然解决了数据不一致的问题,但是由于请求A在更新完数据库之后,需要休眠M秒再次淘汰缓存,一定程度上影响了数据更新操纵的吞吐量。可以实验将等待M秒更新redis的操纵放到另一个单独的线程(比如消息队列 + 重试机制)。可以有用缓解吞吐量降低的问题。
异常情况2
A请求举行读操纵,此时redis缓存中没有数据,因此直接从数据库中读取数据
B请求举行写操纵,先淘汰缓存,再更新数据库
A请求举行将从数据库中读到的老数据,更新到redis。此时产生数据不一致问题。
该种异常情况发生概率极低,一样平常读操纵比写操纵要快。如有担心,可以接纳上述的延时删除战略
方案2: 先更新数据库,后更新淘汰缓存
正常情况
A请求举行写操纵,先更新数据库,再淘汰缓存
B请求举行读操纵,由于A请求已将缓存淘汰,B请求没有在redis中发现所需数据,因此从数据库中读取数据,并更新缓存到redis中
异常情况1
A请求举行写操纵,先更新数据库
B请求举行读操纵,由于A请求尚未淘汰缓存,B请求在redis中发现所需数据,因此直接返回老数据,产生了数据不一致的问题
A请求淘汰缓存。
C请求举行读操纵,发现redis中没有数据,因此从数据库中读取新数据,并更新至缓存。数据不一致的问题解决。
该场景下,数据终极一致,只是在高并发下产生了一小段时间的数据不一致。
异常情况2
A请求举行读操纵,此时redis缓存中没有数据,因此直接从数据库中读取数据
B请求举行写操纵,更新数据库,并将redis中缓存举行了淘汰(虽然此时redis中并没有任何的缓存)
A请求将从数据库中读到的老数据,更新到redis。此时产生数据不一致问题。
该种异常情况发生概率极低,一样平常读操纵比写操纵要快。如有担心,可以接纳上述的延时删除战略
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
本帖子中包含更多资源
您需要
登录
才可以下载或查看,没有账号?
立即注册
x
回复
使用道具
举报
0 个回复
正序浏览
返回列表
快速回复
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
or
立即注册
本版积分规则
发表回复
回帖并转播
发新帖
回复
天津储鑫盛钢材现货供应商
论坛元老
这个人很懒什么都没写!
楼主热帖
linux shell 脚本 入门到实战详解[⭐建 ...
Flutter 3.0 发布啦~快来看看有什么新 ...
我与Java Boy的10年-从小白到资深架构 ...
【MySQL】数据库多表操作通关教程(外键 ...
深度解析KubeEdge EdgeMesh 高可用架构 ...
影音娱乐应用开发,这些关键词请查收 ...
读Java性能权威指南(第2版)笔记06_数 ...
zset底层的数据结构为什么使用调表而不 ...
腾讯会议使用OBS虚拟摄像头
SpringBoot中Tomcat和SpringMVC整合源 ...
标签云
AI
运维
CIO
存储
服务器
浏览过的版块
Nosql
SQL-Server
程序人生
移动端开发
分布式数据库
鸿蒙
DevOps与敏捷开发
快速回复
返回顶部
返回列表