Redis怎么保持缓存与数据库一致性?
将不一致分为三种情况:
1. 数据库有数据,缓存没有数据;
2. 数据库有数据,缓存也有数据,数据不相等;
3. 数据库没有数据,缓存有数据。
在讨论这三种情况之前,先说明一下我使用缓存的策略,也是大多数人使用的策略,叫做 Cache Aside Pattern。简而言之,就是
1. 首先尝试从缓存读取,读到数据则直接返回;如果读不到,就读数据库,并将数据会写到缓存,并返回。
2. 需要更新数据时,先更新数据库,然后把缓存里对应的数据失效掉(删掉)。
读的逻辑大家都很容易理解,谈谈更新。如果不采取我提到的这种更新方法,你还能想到什么更新方法呢?大概会是:先删除缓存,然后再更新数据库。这么做引发的问题是,如果A,B两个线程同时要更新数据,并且A,B已经都做完了删除缓存这一步,接下来,A先更新了数据库,C线程读取数据,由于缓存没有,则查数据库,并把A更新的数据,写入了缓存,最后B更新数据库。那么缓存和数据库的值就不一致了。另外有人会问,如果采用你提到的方法,为什么最后是把缓存的数据删掉,而不是把更新的数据写到缓存里。这么做引发的问题是,如果A,B两个线程同时做数据更新,A先更新了数据库,B后更新数据库,则此时数据库里存的是B的数据。而更新缓存的时候,是B先更新了缓存,而A后更新了缓存,则缓存里是A的数据。这样缓存和数据库的数据也不一致。按照我提到的这种更新缓存的策略,理论上也是有不一致的风险的,之前在其他的博客文章有看到过,只不过概率很小,我们暂时可以不考虑,后面我们有其他手段来补救。讨论完使用缓存的策略,我们再来看这三种不一致的情况。
1. 对于第一种,在读数据的时候,会自动把数据库的数据写到缓存,因此不一致自动消除.
2. 对于第二种,数据最终变成了不相等,但他们之前在某一个时间点一定是相等的(不管你使用懒加载还是预加载的方式,在缓存加载的那一刻,它一定和数据库一致)。这种不一致,一定是由于你更新数据所引发的。前面我们讲了更新数据的策略,先更新数据库,然后删除缓存。因此,不一致的原因,一定是数据库更新了,但是删除缓存失败了。
3. 对于第三种,情况和第二种类似,你把数据库的数据删了,但是删除缓存的时候失败了。
因此,最终的结论是,需要解决的不一致,产生的原因是更新数据库成功,但是删除缓存失败。
解决方案大概有以下几种:
1. 对删除缓存进行重试,数据的一致性要求越高,我越是重试得快。
2. 定期全量更新,简单地说,就是我定期把缓存全部清掉,然后再全量加载。
3. 给所有的缓存一个失效期。
第三种方案可以说是一个大杀器,任何不一致,都可以靠失效期解决,失效期越短,数据一致性越高。但是失效期越短,查数据库就会越频繁。因此失效期应该根据业务来定。
并发不高的情况:
读: 读redis->没有,读mysql->把mysql数据写回redis,有的话直接从redis中取;
写: 写mysql->成功,再写redis;
并发高的情况:
读: 读redis->没有,读mysql->把mysql数据写回redis,有的话直接从redis中取;
写:异步话,先写入redis的缓存,就直接返回;定期或特定动作将数据保存到mysql,可以做到多次更新,一次保存
Redis怎么保持缓存与数据库一致性?的更多相关文章
- 缓存与数据库一致性之二:高并发下的key重建(先淘汰cache再写db)的问题
一.为什么数据会不一致 回顾一下上一篇文章<缓存与数据库一致性之一:缓存更新设计>中对缓存.数据库进行读写操作的流程. 写流程: (1)先淘汰cache (2)再写db 读流程: (1)先 ...
- Redis缓存和数据库一致性问题
工作中,经常会遇到缓存和数据库数据一致性问题.从理论上设置过期时间,是保证最终一致性的解决方案.这种方案下,我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可 ...
- Redis缓存与数据库一致性解决方案
背景 缓存是数据库的副本,应用在查询数据时,先从缓存中查询,如果命中直接返回,如果未命中,去数据库查询最新数据并返回,同时写入缓存. 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载.是应用架 ...
- redis缓存与数据库一致性问题
一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求 “缓存+数据库” 必须保持一致性的话,最好不要做这个方案,即:读请求和写请求串行化,串到一个内存队列里去. ...
- 缓存与数据库一致性之三:缓存穿透、缓存雪崩、key重建方案
一.缓存穿透预防及优化 缓存穿透是指查询一个根本不存在的数据,缓存层和存储层都不会命中,但是出于容错的考虑,如果从存储层查不到数据则不写入缓存层,如图 11-3 所示整个过程分为如下 3 步: 缓存层 ...
- 分布式-技术专区-Redis和MySQL缓存一致性问题
1.Redis 缓存和 MySQL 数据如何实现一致性 需求起因 缓存和数据库一致性解决方案 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节.所以,就需要使用redis做一个缓冲操 ...
- Docker安装canal、mysql进行简单测试与实现redis和mysql缓存一致性
一.简介 canal [kə'næl],译意为水道/管道/沟渠,主要用途是基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费. 早期阿里巴巴因为杭州和美国双机房部署,存在跨机房同步的业务需求 ...
- Redis使用总结(二、缓存和数据库双写一致性问题)
首先,缓存由于其高并发和高性能的特性,已经在项目中被广泛使用.在读取缓存方面,大家没啥疑问,都是按照下图的流程来进行业务操作. 但是在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存.又或者 ...
- Redis面试篇 -- 如何保证缓存与数据库的双写一致性?
如果不是严格要求“缓存和数据库”必须保证一致性的话,最好不要做这个方案:即 读请求和写请求串行化,串到一个内存队列里面去.串行化可以保证一定不会出现不一致的情况,但会导致系统吞吐量大幅度降低. 解决这 ...
随机推荐
- Oracle 11gR2 Database UNDO表空间使用率居高不下处理
一.UNDO表空间监控图 Prometheus监控的到UNDO表空间使用率超过90%(90%为所有表空间告警阈值).从图中可以看到,多次增加UNDO表空间的DATAFILE,UNDO表空间达到40GB ...
- day20 类的约束
今日所学 : 1 .类的约束 2 .异常处理 try except raise 3. MD5加密 4. 日记处理(不要记,留一份,侧重点再用) 1 .类的约束 1) 写一个父类,父类中的某个方法要抛出 ...
- flask-admin有用的例子
flask-admin主页: https://github.com/flask-admin/flask-admin flask-admin克隆地址: https://github.com/flask- ...
- 一个表中多个字段对应另一个表的ID(SQL查询)
A数据表中多个字段对应B数据表的ID, 现在要把B表的其他字段一起查询出来 一.数据表: 1.SPEED_DETECTION_ROAD 它的 START_POINT_ID 和 END_POINT_ID ...
- easyui datagrid 首次不加载做法
我们一般遇到首次不执行查询,只有你点击查询按钮才查询的功能 我使用easyui的datagird做法是这样的: onBeforeLoad: function (param) { var firstLo ...
- ubuntu下用vagrant搭建集群环境
1.安装virtualbox 终端输入:sudo apt-get install virtualbox(事实从来都不是一番风顺的.......) 正在读取软件包列表... 完成 正在分析软件包的依赖关 ...
- 3-log4j2之输出日志到文件
一.添加maven依赖 <dependencies> <dependency> <groupId>org.apache.logging.log4j</grou ...
- 2-log4j2之使用根控制器输出日志到控制台
一.添加maven依赖 <!-- 使用aliyun镜像 --> <repositories> <repository> <id>aliyun</i ...
- Appium环境搭建过程中遇到的问题及解决办法
一.[Error: Could not detect Mac OS X Version from sw_vers output: '10.12.6'] 解决办法: 1.vi /Applications ...
- vue国际化插件
1.安装 $ npm install vue-i18n 2.引入 import VueI18n from 'vue-i18n' Vue.use(VueI18n) const i18n = new Vu ...