技术问题:关于redis的内存数据和数据库里面的数据如何保持数据的一致性

本文讨论了在数据库和缓存同步时如何保持数据一致性。两种常见策略是先删除缓存再更新数据库,以及先更新数据库再删除缓存。沈剑老师建议根据业务影响选择顺序,而孤独烟老师指出先删缓存可能导致并发时的数据脏读。在大多数情况下,先更新数据库再删除缓存可能是更好的选择,尽管仍存在并发问题,但其概率较低。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言: 在寒假找实习的过程中,科大讯飞技术面试官问我:
关于redis的内存数据和数据库里面的数据如何保持数据的一致性

当我们在做数据库与缓存数据同步时,究竟更新缓存,还是删除缓存,究竟是先操作数据库, 还是操作缓存?

1. 数据缓存

  • 为何要使用数据缓存?
    在一些应用场景,某些数据访问频率高, 更新频率低,为了减少对数据库的访问频率以及加快访问速度,将这些热点数据缓存到内存当中。

  • 哪类数据适合数据缓存?

一般而言,对于经常变化的数据,不适合做缓存,一方面会增加系统的复杂性(缓存的更新, 缓存脏数据),另一方面给系统带来一定的不稳定性(缓存系统的维护)

  • 缓存的利与弊?
    上缓存的优点:
    1. 缩短服务响应时间
    2. 增大系统吞吐量
    3. 减轻数据库压力
    弊端:
    1. 系统复杂度增加
    2. 系统分布式存在很多坑
    3. 缓存和数据库一致性的问题

2.如何保证缓存和数据库一致性

观点一:不更新缓存,而是删除缓存,由下个请求取缓存,如果不存在在读取数据库,写入缓存

由此引发出来的问题:
先删除缓存,然后再更新数据库, 还是先更新数据库,再删除缓存呢?

先来看看大佬们怎么说。
《【58沈剑架构系列】缓存架构设计细节二三事》58沈剑:
对于一个不能保证事务性的操作,一定涉及“哪个任务先做,哪个任务后做”的问题,解决这个问题的方向是:如果出现不一致,谁先做对业务的影响较小,就谁先执行。
假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败,则只会引发一次Cache miss。
假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致。

沈剑老师说的没有问题,不过没完全考虑好并发请求时的数据脏读问题,让我们再来看看孤独烟老师《分布式之数据库和缓存双写一致性方案解析》:

先删缓存,再更新数据库
该方案会导致请求数据不一致
同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:
(1)请求A进行写操作,删除缓存
(2)请求B查询发现缓存不存在
(3)请求B去数据库查询得到旧值
(4)请求B将旧值写入缓存
(5)请求A将新值写入数据库
上述情况就会导致不一致的情形出现。而且,如果不采用给缓存设置过期时间策略,该数据永远都是脏数据。

所以先删缓存,再更新数据库并不是一劳永逸的解决方案,再看看先更新数据库,再删缓存这种方案怎么样?

先更新数据库,再删缓存这种情况不存在并发问题么?
不是的。假设这会有两个请求,一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生
(1)缓存刚好失效
(2)请求A查询数据库,得一个旧值
(3)请求B将新值写入数据库
(4)请求B删除缓存
(5)请求A将查到的旧值写入缓存
ok,如果发生上述情况,确实是会发生脏数据。
然而,发生这种情况的概率又有多少呢?
发生上述情况有一个先天性条件,就是步骤(3)的写数据库操作比步骤(2)的读数据库操作耗时更短,才有可能使得步骤(4)先于步骤(5)。可是,大家想想,数据库的读操作的速度远快于写操作的(不然做读写分离干嘛,做读写分离的意义就是因为读操作比较快,耗资源少),因此步骤(3)耗时比步骤(2)更短,这一情形很难出现。

所以,如果你想实现基础的缓存数据库双写一致的逻辑,那么在大多数情况下,在不想做过多设计,增加太大工作量的情况下,请先更新数据库,再删缓存!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值