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
什么是缓存击穿 在谈论缓存击穿之前,我们先来回忆下从缓存中加载数据的逻辑,如下图所示 因此,如果黑客每次故意查询一个在缓存内必然不存在的数据,导致每次请求都要去存储层去查询,这样缓存就失去了意义.如果 ...
随机推荐
- centos6.8安装python3.7.3报错Can't connect to HTTPS URL because the SSL module is not available问题解决
环境:CentOS release 6.8 (Final) # 直接编译python3.7在使用pip3安装依赖的时候报错: Can't connect to HTTPS URL because th ...
- spring-data-redis数据类型
一.引入依赖 <!-- 缓存 --> <dependency> <groupId>redis.clients</groupId> <artifac ...
- realsense SDK编译 debug
1>------ 已启动全部重新生成: 项目: ZERO_CHECK, 配置: Debug x64 ------1> Checking Build System1> CMake do ...
- 【Tomcat】Tomcat 配置JNDI数据源(三)
数据源的由来 在Java开发中,使用JDBC操作数据库的四个步骤如下: ①加载数据库驱动程序(Class.forName("数据库驱动类");) ②连接数据库(Connec ...
- Qt编写气体安全管理系统5-数据监控
一.前言 本项目对设备的监控有四种视图模式,可以任意切换,数据监控.地图监控.设备监控.曲线监控,其中数据监控是最常用的,所以在主界面导航中也排在第一位,综合观察分析了很多气体安全或者组态监控软件,大 ...
- 通过直方图进行PCA准备
import graphviz import mglearn from mpl_toolkits.mplot3d import Axes3D from sklearn.datasets import ...
- LeetCode_344. Reverse String
344. Reverse String Easy Write a function that reverses a string. The input string is given as an ar ...
- 【JS新手教程】JS中的split()方法,拆分字符串
该方法具体如代码和图中的注释,直接在语句后面加注释了.格式:要拆分的字符串.split(拆分依据的字符)例如该文中的例子,拆分人名,电话,地址.该文中用了个文本框,文本框中需要输入的格式是:人名,电话 ...
- Intellij热部署插件JRebel的详细配置及图解
参考博客地址:https://blog.csdn.net/nyotengu/article/details/80629631 参考博客地址:https://blog.csdn.net/weixin_4 ...
- eclipse设置格式化tab为4个空格和idea一样