原文(缓存更新的套路):看到好些人在写更新缓存数据代码时,先删除缓存,然后再更新数据库,而后续的操作会把数据再装载的缓存中。然而,这个是逻辑是错误的。试想,两个并发操作,一个是更新操作,另一个是查询操作,更新操作删除缓存后,查询操作没有命中缓存,先把老数据读出来后放到缓存中,然后更新操作更新了数据库。于是,在缓存中的数据还是老的数据,导致缓存中的数据是脏的,而且还一直这样脏下去了。

视图分析:

写流程(更新策略)

  1. 先淘汰 cache(删除缓存);
  2. 再写 DB(更新数据库)。

读流程

  1. 先读 cache,如果数据命中 hit 则返回;
  2. 如果数据未命中 miss 则读 DB;
  3. 将 DB 中读取出来的数据入缓存。

什么情况下可能出现缓存和数据库不一致呢?

在分布式环境下,数据的读写都是并发的,上游有多个应用,通过一个服务的多个部署(为了保证可用性,一定是部署多份的),对同一个数据进行读写,在数据库层面并发的读写并不能保证完成顺序,也就是说后发出的读请求很可能先完成(读出脏数据):

  1. 发生了写请求 A,A 的第一步淘汰了 cache(如上图中的1);
  2. A 的第二步写数据库,发出修改请求(如上图中的2);
  3. 发生了读请求 B,B 的第一步读取 cache,发现 cache 中是空的(如上图中的步骤3);
  4. B 的第二步读取数据库,发出读取请求,此时 A 的第二步写数据还没开始,读出了一个脏数据放入 cache(如上图中的步骤4)。

最终导致缓存与数据库不一致。

先更新数据库,后删除缓存(建议,使用场景最多),但是,是不是这个就不会有并发问题了?不是的,比如,一个是读操作,但是没有命中缓存,然后就到数据库中取数据,此时来了一个写操作,写完数据库后,让缓存失效,然后,之前的那个读操作再把老的数据放进去,所以,会造成脏数据。

Redis更新的正确方法的更多相关文章

  1. edis更新的正确方法

    Redis更新的正确方法 https://www.cnblogs.com/westboy/p/8696607.html redis做缓存,怎么更新里面的数据 https://blog.csdn.net ...

  2. Web 性能优化: 使用 Webpack 分离数据的正确方法

    摘要: Webpack骚操作. 原文:Web 性能优化: 使用 Webpack 分离数据的正确方法 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 制定向用户提供文件的最佳方式可能是一 ...

  3. dedecms网站迁移时记得将安装目录放空 附迁移的正确方法

    这段时间在赶一些新项目,我们建站一般都在本地服务器搭建起来,测试得差不多了才传到网上,这样对蜘蛛也相对友好一些,要不然改来改去变化太大给搜索引擎的第一印象很不好.但是由于本地环境和服务器环境还是有一些 ...

  4. mysqldump 逻辑备份的正确方法【转】

    1. 利用mysqldump进行逻辑备份 1)全逻辑备份: mysqldump -uxxx -p --flush-logs --delete-master-logs --all-databases & ...

  5. 安装ANSYS19.0的正确方法(附下载)

    安装ANSYS19.0的正确方法 卸载干净旧版本ANSYS 安装或重新安装之前必须先卸载干净,安装过旧版本ANSYS的也要确保卸载干净.电脑环境准备参考以下内容 ANSYS 卸载后重装需要注意的问题_ ...

  6. (一)Redis for Windows正确打开方式

    目录 (一)Redis for Windows正确打开方式 (二)Redis for 阿里云公网连接 (三)Redis for StackExchange.Redis 下载地址 官网.中文网1 及 中 ...

  7. AbpVnext使用分布式IDistributedCache Redis缓存(自定义扩展方法)

    AbpVnext使用分布式IDistributedCache缓存from Redis(带自定义扩展方法) 我的依赖包的主要版本以及Redis依赖如下 1:添加依赖 <PackageReferen ...

  8. java并发编程(三)线程挂起,恢复和终止的正确方法

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17095733    下面我们给出不用上述两个方法来实现线程挂起和恢复的策略--设置标志位. ...

  9. mysql如果数据不存在,则插入新数据,否则更新的实现方法

    mysql如果数据不存在,则插入新数据,否则更新的实现方法 //如果不存在,则插入新数据 $sql = "INSERT INTO {$ecs->table('cat_lang')} ( ...

随机推荐

  1. 目标检测-ssd

    intro: ECCV 2016 Oral arxiv: http://arxiv.org/abs/1512.02325 paper: http://www.cs.unc.edu/~wliu/pape ...

  2. jquery----data使用

    - .data() - .data("key", value) 保存值,value可以是字符串,也可以是数组,也可以是jquery对象- .data("key" ...

  3. C#中的预处理指令详解

    这篇文章主要介绍了C#中的预处理指令详解,本文讲解了#define 和 #undef.#if.#elif.#else和#endif.#warning和#error.#region和#endregion ...

  4. Angular2学习(一)

    Angular2的新特性: angular2的核心: 模块.组件.元数据.模板.数据绑定.服务.指令.依赖注入.模块. 组件:层层嵌套,形成组件树.父子组件沟通有输入和输出接口 组件包含JavaScr ...

  5. 存储过程,存储函数(Oracle)

    存储过程和存储函数 指存储在数据库中供所有用户程序调用的子程序叫存储过程.存储函数. 存储过程和存储函数的区别? 存储函数:可以通过return 语句返回函数值. 存储过程:不能 除此之外我们可以认为 ...

  6. BZOJ1845 [Cqoi2005] 三角形面积并 扫描线 计算几何

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1845 题意概括 给出n个三角形,求其面积并. 题解 有一个很经典的扫描线题目:矩形面积并.那个比较 ...

  7. 075 importSTV的使用,与bulkload的使用

    一:由HDFS将数据直接导入到HBase中 1.生成TSV文件 2.内容 3.上传到HDFS 4.运行 export HBASE_HOME=/etc/opt/modules/hbase-0.98.6- ...

  8. wxpython安装,demo下载

    wxPython介绍      wxPython是Python语言的一套优秀的GUI图形库.wxPython可以很方便的创建完整的.功能键全的GUI用户界面. wxPython安装 本安装采用pip自 ...

  9. 《Gradle权威指南》--Android Gradle测试

    No1: Android既可以用传统的JUnit测试,也可以用Android的instrument测试. No2: 当我们运行测试的时候,androidTest SourceSet会被构建成一个可以安 ...

  10. python中执行shell的两种方法总结

    这篇文章主要介绍了python中执行shell的两种方法,有两种方法可以在Python中执行SHELL程序,方法一是使用Python的commands包,方法二则是使用subprocess包,这两个包 ...