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

视图分析:

写流程(更新策略)

  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. hdu6107 倍增法st表

    发现lca的倍增解法和st表差不多..原理都是一样的 /* 整篇文章分成两部分,中间没有图片的部分,中间有图片的部分 分别用ST表求f1,f2表示以第i个单词开始,连续1<<j行能写多少单 ...

  2. python3 + selenium 使用 JS操作页面滚动条

    js2 = "window.scrollTo(0,0);" #括号中为坐标 当不知道需要的滚动的坐标大小时: weizhi2 = driver.find_element_by_id ...

  3. collectd+influxDB+Grafana搭建性能监控平台

    网上查看了很多关于环境搭建的文章,都比较久远了很多安装包源都不可用了,今天收集了很多资料组合尝试使用新版本来搭建,故在此记录. 采集数据(collectd)-> 存储数据(influxdb) - ...

  4. 步步为营-33-Md5(32)加密与Base64加密

    说明: 1:直接贴码 using System; using System.Collections.Generic; using System.ComponentModel; using System ...

  5. 多线程中实现ApplicationContextAware接口获取需要的bean,applicationContext.getBea未返回也未报错

    唉,面试失败了有点难过. https://q.cnblogs.com/q/95168/#a_208239

  6. Python int 中 add abs 方法

    1+1 实际等于1.__add__(1) __abs__ 取绝对值

  7. Redis数据结构之哈希

    这个部分依旧分为两个步骤,一个是redis客户端,一个是java的客户端 一:Redis客户端 1.get与set 2.删除 3.增加 4.是否存在 hexists myhash2 age 5.获取长 ...

  8. 062 hive中的常用方法(case,cast,unix_timestamp)

    1.case的用法 )格式1 case col when value then '' when value then '' else '' end )格式2 case when col='value' ...

  9. Python6 - 函数总结

    一.函数的基本知识 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 1.1函数定义规则 ...

  10. PHP 随笔记

    SQL插入数据并返回刚插入数据行的主键ID INSERT INTO `peoplespublic`.`demo` (`id`, `name`, `content`, `time`, `file`) V ...