Redis缓存如何保证一致性
为什么使用Redis做缓存
MySQL缺点
- 单机连接数目有限
- 对数据进行写速度慢
Redis优点
- 内存操作数据速度快
- IO复用,速度快
- 单线程模型,避免线程切换带来的开销,速度快
一致性问题
读数据的时候首先去Redis里读,没有读到再去MySQL里读,读回来之后更新到Redis里作为下一次的缓存。写数据的时候回产生数据不一致的问题,无论是先写到Redis里再写MySQL还是先写MySQL再写Redis,这两步写操作不能保证原子性,所以会出现Redis和MySQL里的数据不一致。无论采取何种方式都不能保证强一致性,如果对Redis里的数据设置了过期时间能够保证最终一致性,对架构做的优化只能降低不一致性发生的概率,不能从根本上避免不一致性。
根据写入的顺序不同分为四种。
先删缓存,再更新数据库
这种操作的问题?
一般考虑某种策略的问题都是考虑该种策略会不会导致被删除的脏数据由于时序混乱再次被读线程从MySQL中读出来。A线程写数据,B线程读数据,A线程删除了缓存,B线程读数据发现缓存没有命中从数据库中读数据,B线程把读出的旧数据写到Redis里,A线程把新数据写回去。和下面的先写数据库再删缓存相比,这种方式显著的缺点
- 先删缓存,所以当两个线程并发的时候很大几率会出现缓存不命中,一旦缓存不命中,在写线程修改MySQL完成之前读进来的永远是脏数据
- 在缓存到期之前Redis里一直是脏数据
解决策略
延迟双删,双删就是在更新完数据库后再删一次。不过延迟双删中更新数据库之前的删除还有什么意义?延迟的目的是为了删除在写MySQL期间读线程可能把脏数据再次读到Redis里,延迟的时间参照一次从MySQL读数据并写入Redis的时间
Cache Aside Pattern--先写数据库,再删缓存
为什么更新数据库后不更新而是删除缓存?
- 更新缓存的操作不是必须的。可能缓存里的数据并没有被读到,就会被下一次更新MySQL操作带来Redis更新操作覆盖,那么本次更新操作就是无意义的。
- 更新缓存代价大。如果缓存里的数据不是把MySQL里的数据直接存下来,而是需要经过某种复杂的运算,那么这种不必要的更新会带来更大的浪费。
这种操作的问题?
- 并发问题。A线程读数据但没有命中,B线程写数据。A线程读到了MySQL的旧数据,B线程写了新的数据进MySQL,B线程删除了Redis中旧数据的缓存,A用旧数据写到了Redis缓存里。此时Redis里就是旧的脏数据。但这种case出现的概率较低,需要Redis缓存失效同时出现线程写入操作,而且理论上A线程从MySQL中读数据应该更快的返回。
解决方案?
每个写MySQL线程写完后延时一定时间在去删Redis中的缓存。
Write Behind Caching Pattern--只更缓存,不更MySQL,MySQL由缓存异步的更新
Redis缓存如何保证一致性的更多相关文章
- Redis缓存和数据库一致性问题
工作中,经常会遇到缓存和数据库数据一致性问题.从理论上设置过期时间,是保证最终一致性的解决方案.这种方案下,我们可以对存入缓存的数据设置过期时间,所有的写操作以数据库为准,对缓存操作只是尽最大努力即可 ...
- redis缓存与数据库一致性问题
一般来说,如果允许缓存可以稍微的跟数据库偶尔有不一致的情况,也就是说如果你的系统不是严格要求 “缓存+数据库” 必须保持一致性的话,最好不要做这个方案,即:读请求和写请求串行化,串到一个内存队列里去. ...
- Redis缓存与数据库一致性解决方案
背景 缓存是数据库的副本,应用在查询数据时,先从缓存中查询,如果命中直接返回,如果未命中,去数据库查询最新数据并返回,同时写入缓存. 缓存能够有效地加速应用的读写速度,同时也可以降低后端负载.是应用架 ...
- redis,缓存雪崩,粗粒度锁,缓存一致性
1, redis单线程为什么快 io多路复用技术 单线程避免多线程的频繁切换问题 memcache缺点 kv形式数据 没有持久化mongodb 海量数据的访问效率 mr的计算模型文档就是类似json的 ...
- Redis缓存穿透、击穿、雪崩,数据库与缓存一致性
Redis作为高性能非关系型(NoSQL)的键值对数据库,受到了广大用户的喜爱和使用,大家在项目中都用到了Redis来做数据缓存,但有些问题我们在使用中不得不考虑,其中典型的问题就是:缓存穿透.缓存雪 ...
- Redis 缓存 + Spring 的集成示例(转)
<整合 spring 4(包括mvc.context.orm) + mybatis 3 示例>一文简要介绍了最新版本的 Spring MVC.IOC.MyBatis ORM 三者的整合以及 ...
- Redis缓存你必须了解的!
不管你是从事Python.Java.Go.PHP.Ruby等等… Redis都应该是一个比较熟悉的中间件.而大部分经常写业务代码的程序员,实际工作中或许只用到了set value.get value两 ...
- Redis缓存穿透和缓存雪崩以及解决方案
Redis缓存穿透和缓存雪崩以及解决方案 Redis缓存穿透和缓存雪崩以及解决方案缓存穿透解决方案布隆过滤缓存空对象比较缓存雪崩解决方案保证缓存层服务高可用性依赖隔离组件为后端限流并降级数据预热缓存并 ...
- redis 缓存击穿 看一篇成高手系列3
什么是缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的逻辑,如下图所示 因此,如果黑客每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查询,这样缓存就失去了意义.如果 ...
随机推荐
- Ubuntu16.04下升级Python到3.6.5
本文链接:https://blog.csdn.net/chaiyu2002/article/details/82698376原帖存于IT老兵博客.Ubuntu16.04下升级Python到3.6.5 ...
- 005 Spring和SpringBoot中的@Component 和@ComponentScan注解
今天在看@ComponentScan,感觉不是太理解,下面做一个说明. 1.说明 ComponentScan做的事情就是告诉Spring从哪里找到bean 2.细节说明 如果你的其他包都在使用了@Sp ...
- git-scm教程摘要
Git 有三种状态 已提交(committed).已修改(modified)和已暂存(staged) 已提交表示数据已经安全的保存在本地数据库中. 已修改表示修改了文件,但还没保存到数据库中. 已暂存 ...
- Fiddler抓包工具版面认识(一)
Fiddler是一个蛮好用的抓包工具,可以将网络传输发送与接受的数据包进行截获.重发.编辑.转存等操作.也可以用来检测网络安全.反正好处多多,举之不尽呀!当年学习的时候也蛮费劲,一些蛮实用隐藏的小功能 ...
- oraagent.bin High Memory Usage as Dependent Listener was Removed/Renamed
Grid Infrastructure oraagent.bin process using huge amount of memory and forking huge number of thr ...
- (转载)文献可视化--vosviewer入门
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/weixin_42613298/artic ...
- PAT 甲级 1071 Speech Patterns (25 分)(map)
1071 Speech Patterns (25 分) People often have a preference among synonyms of the same word. For ex ...
- 【ROC+AUC】
http://m.elecfans.com/article/736801.html https://blog.csdn.net/xyz1584172808/article/details/818392 ...
- AD域策略启动关机脚本不执行的注意事项
其实主要是脚本路径的问题. 错误一: 直接使用右侧的添加按钮,添加了预控的本地路径.如上图第二行. 错误二: 直接使用右侧的添加按钮,添加了脚本的网络路径,如上图第三行. 正确的方法: 点击下方的显示 ...
- docker容器中解决出现:^H^H^H^H
docker容器中解决出现:^H^H^H^H 环境:docker容器是debain系统 解决: 把stty erase ^H 添加到.bash_profile中 vim /etc/profile st ...