当前没有框架能够保证redis的数据和数据库的完全一致性,所以需要 我们自己在性能和一致性上作取舍。

使用到缓存的场景

 这里讲到的是缓存和数据库的一致性问题。当查询数据库数据的时候,才涉及到缓存的利用上,所以缓存的引入是为了让查询数据的时候提高效率;而当发生增、删、改数据的时候,对于缓存来说是要让数据库和缓存发生一致性的改变,进而能让缓存在数据查询时候能继续起作用。

下图就是两种在redis缓存数据库内容时的使用。

对于缓存的一致性操作的选择

明确了缓存的使命------在查询数据库信息时,提前将数据进行缓存,既减少了数据库io,也提高了查询效率。

那么如一个节点的两个图:
缓存的生成,是在首次查询或者缓存过期时间到或者缓存被其他业务删除,进而需要在数据库查询完毕之后,将数据库内容同步到缓存中。
那当数据发生增删改时,涉及到两个方向的选择
1、是删除还是更新redis缓存
2、是先删除\更新缓存,再操作数据库;还是先操作数据库,再删除\更新缓存。
下面一一讨论

(1)数据发生变化,删除还是更新redis缓存

更新:数据发生增删改,把缓存的内容 重新用redis的set操作,赋予新值。
删除:在查询时,发现缓存已经不存在,去数据库查询之后,同步到redis缓存。

1、如何选择,可以使用排除方法,首先讨论更新。
(1)、redis更新是放在数据库操作的前。
线程1: redis更新 ---------------------------数据库更新
线程2:redis更新-------------------------数据库更新
(2)、redis更新是放在数据库操作的后。
线程1: 数据库更新 ---------------------------redis更新
线程2:数据库更新-------------------------redis更新
可以看到这样的场景,当线程1和2完成之后,此时缓存和数据库是不一致的。
2、写多读少:上面一直讨论缓存的目的是给读操作使用的,那么每修改一次就写入一次缓存,无疑大大的做无用功。
3、如果缓存是需要计算加工的数据:即查询到数据库值之后,缓存的值需要再做计算,那么每一次修改将很损耗性能。

总结:综合上面三点,删除要比更新的效率和避免数据不一致的效果更好。

(1)数据发生变化,先删除还是先操作数据库

1、 先更新数据库,再删除缓存
2、先删除缓存,再更新数据库
下面一一讨论:
(1)先更新数据库,再删除缓存
①如果更新数据库失败,那么程序捕获异常,之后不进行删除缓存操作。
②如果更新数据库成功,但是删除缓存失败。
针对②可以采用异步操作的办法,把删除失败的key给到队列当中,由线程池来执行失败重试。
或者可以利用canal 监听数据库修改 进而发生删除的操作。

(2)先删除缓存,再更新数据库
这种方式可能存在以下三种异常情况

1、删除缓存失败,这时可以通过程序捕获异常,直接返回结果,不再继续更新数据库,所以不会出现数据不一致的问题
2、删除缓存成功,更新数据库失败。此时不会发生数据不一致现象。
3、下图的场景,两个线程执行完成之后,会导致redis和数据库的不一致。

解决第三种情况可以使用 延时双删的策略,如下图:

这里讨论一下延时双删如何解决第三种异常情况,
1、线程2在查询数据库旧值之后,更新缓存,此时数据不一致,所以需要再次删除。
2、休眠时间,是为了在线程2写入缓存之后,线程1才发生删除缓存,不延时,可能导致线程2还没写入缓存,线程1就完成了删除缓存,那么最终的结果 还是数据不一致。
3、无论如何线程2并利用的是旧数据,这点没办法更改这点容错率还是支持的,毕竟要是发生在删除缓存前一秒还会利用缓存,此时数据还是最新数据,而删除缓存之后的一秒,才会到数据库去查最新数据,这个时间差的代价无论如何一定存在。
伪代码:

public void update(String key, Object data) {// 首先删除缓存redisCache.delKey(key);// 更新数据库db.updateData(data);// 休眠一段时间,时间依据数据的读取耗费的时间而定Thread.sleep(500);// 再次删除缓存redisCache.delKey(key);

总结

1、选择删除缓存 而不是更新
2、如果先修改数据库,再删除缓存,缓存删除成功的机制可以用异步的失败重试机制。
3、如果先删除缓存,再修改数据库,可以使用延时双删的机制。

文章摘录至https://blog.csdn.net/chanmufeng/article/details/122933214

redis和数据库的一致性问题的解决方案相关推荐

  1. Redis与数据库缓存一致性问题

    一.Redis 数据一致性问题产生的原因 对 Redis和数据库的操作有 2 种方案: 1.先操作(删除) Redis,再操作数据库 2.先操作数据库,再操作(删除) Redis 上述二种方案,都希望 ...

  2. 如何保证Redis和数据库的一致性

    在使用Redis中,我们都会遇到同样的问题,当一个请求要更新数据库时,Redis缓存显然也要被更新.我们必须要保证两者的一致性. 而数据库和Redis是两个不同的进程,很难保证两个进程更新都一定能完成 ...

  3. 【Redis】--缓存双写一致性分析、解决方案

    目录 一.缓存双写一致性场景 1.先更新数据库,再更新缓存 2.先更新数据库,再删除缓存 2.1.存在的问题一:删除缓存失败,导致Redis和mysql的数据不一致. 2.2.存在的问题二:删除缓存成 ...

  4. Redis(六) 数据库和缓存的一致性问题

    文章目录 一 先上结论 二 四种常用的缓存更新策略: 三 写操作的缓存更新策略分析 一 双更策略: 二 删除策略: 三 延时双删策略: 四 失败重试 同步重试: 异步重试: 借助消息队列: 订阅数据库 ...

  5. 项目优化:当使用redis减少数据库压力时,遇到redis写入失败,造成读取数据问题的解决方案

    场景: 我们项目用到了mq,有一个专门的服务在跑异步任务去发mq,这个mq的数据不是从数据库里面查的,而是从redis里面取的,之所以这么做,有两个原因: 1.使用redis减少数据库的压力: 2.本 ...

  6. 如何保证redis和数据库数据的一致性

    首先能放在缓存中的数据,应该是即时性和数据一致性要求不高或者访问量大但是更新频率不高的数据.所以一般只需要保证redis和数据库数据的最终一致性即可,此时只需要在数据存入缓存的时候加上失效时间,这样到 ...

  7. Redis 缓存数据库

    Redis 缓存数据库 第1章 Redis简介: redis是使用C语言编写的开源的,支持网络,基于内存,可持久性的键值对存储数据库,2013年5月之前,Redis是最流行的键值对存储数据库 Redi ...

  8. 缓存与数据库的一致性:先操作缓存还是先操作数据库?

    数据缓存 在我们实际的业务场景中,一定有很多需要做数据缓存的场景,比如售卖商品的页面,包括了许多并发访问量很大的数据,它们可以称作是是"热点"数据,这些数据有一个特点,就是更新频率 ...

  9. 如何保证缓存和数据库的一致性?

    文章目录 1. 问题分析 2. Cache-Aside 2.1 读缓存 2.2 写缓存 2.3 延迟双删 2.4 如何确保原子性 3. Read-Through/Write-Through 3.1 R ...

最新文章

  1. LeetCode 之Two Sum
  2. m4a打开服务器运行失败,WINCC打不开项目,服务器运行失败
  3. mysql libs 5.1.71_用python创建数据库监控平台(1)安装MySQL5.7
  4. hdu1428(spfa与记忆化搜索)
  5. 图的遍历(C语言,邻接表存储的图 - DFS,邻接矩阵存储的图 - BFS)
  6. 使用git将本地文件上传到远程仓库
  7. inline函数的注意事项有哪些?
  8. Android handler.obtainMessage()传字符串用法
  9. C语言 · 字符串输入输出函数
  10. Caffe傻瓜系列(5):Blob,Layer and Net以及对应配置文件的编写
  11. linux centos git 自动更新,在centos上搭建git服务器并自动同步代码
  12. Sublime Text快捷键
  13. 分享一波 Altium Designer超全封装库(带3D模型)
  14. 前端预览excel插件_网页实现Excel在线预览方案集合
  15. 推荐一些经典的学习书籍
  16. CQOI2007]涂色paint(BZOJ 1260) 区间动态规划 DP 逆向思维
  17. Android手机界面组成
  18. 将SQL导入JAVA的后续操作
  19. 英文邮件:greetings
  20. 泰拉瑞亚服务器插件注册,泰拉瑞亚服务器 House 圈地教程(Tshock 插件)

热门文章

  1. Android文件下载——多线程下载
  2. ftl模板导出excel_使用freemarker模板引擎导出word或excel文件(代码实现)
  3. 外媒针对鸿蒙系统,外媒再放狠话!华为鸿蒙系统绝对能成功:比安卓iOS系统更开放...
  4. leetcode之DFS+BFS+DSU刷题总结2
  5. FlinkSQL平台化之路-StreamX提交源码剖析
  6. 战地2服务器怎么虚拟人数,战地2 BOT(AI)人数调整教程
  7. SQL Server 数据类型(整数、浮点数据、日期与时间数据、文本和图形数据类型、货币数据类型、位数据类型、二进制数据类型)
  8. linux内核SPI总线驱动分析(一)
  9. html表白 知乎,知乎表白点赞最高的句子,撩人无数!
  10. [Python] 字典操作近两万字大总结(超详细教程)