Redis解决缓存一致性问题

文章目录

☃️概述

由于我们的 缓存的数据源来自于数据库 , 而数据库的 数据是会发生变化的 , 因此,如果当数据库中 数据发生变化,而缓存却没有同步 , 此时就会有 一致性问题存在, 其后果是:

用户使用缓存中的过时数据,就会产生类似多线程数据安全问题,从而影响业务,产品口碑等;怎么解决呢?有如下几种方案

人工编码方式:缓存调用者在更新完数据库后再去更新缓存,也称之为双写方案

由系统本身完成:数据库与缓存的问题交由系统本身去处理

调用者只操作缓存:其他线程去异步处理数据库,实现最终一致

☃️数据库和缓存不一致采用什么方案

综合考虑使用方案一,但是方案一调用者如何处理呢?这里有几个问题

操作缓存和数据库时有三个问题需要考虑:

如果采用第一个方案,那么假设我们每次操作数据库后,都操作缓存,但是中间如果没有人查询,那么这个更新动作实际上只有最后一次生效,中间的更新动作意义并不大,我们可以把缓存删除,等待再次查询时,将缓存中的数据加载出来

  • 删除缓存还是更新缓存?

    • 更新缓存:每次更新数据库都更新缓存,无效写操作较多
    • 删除缓存:更新数据库时让缓存失效,查询时再更新缓存
  • 如何保证缓存与数据库的操作的同时成功或失败?

    • 单体系统,将缓存与数据库操作放在一个事务
    • 分布式系统,利用TCC等分布式事务方案

应该具体操作缓存还是操作数据库,我们应当是先操作数据库,再删除缓存,原因在于,如果你选择第一种方案,在两个线程并发来访问时,假设线程1先来,他先把缓存删了,此时线程2过来,他查询缓存数据并不存在,此时他写入缓存,当他写入缓存后,线程1再执行更新动作时,实际上写入的就是旧的数据,新的数据被旧数据覆盖了。

  • 先操作缓存还是先操作数据库?
    • 先删除缓存,再操作数据库
    • 先操作数据库,再删除缓存

☃️代码实现

根据id查询数据时,如果缓存未命中,则查询数据库,将数据库结果写入缓存,并设置超时时间

根据id修改数据时,先修改数据库,再删除缓存

java 复制代码
@Transactionl
public Result update(){
//	执行更新逻辑


//	删除缓存
}

☃️其他

要保证数据库和Redis缓存之间的一致性,可以采用以下策略:

  • 缓存-旁路(Cache-Aside,Lazy Loading):在这种方式中,应用程序首先检查缓存中是否存在所需数据。如果缓存中存在数据,则直接返回给应用程序。如果缓存中不存在数据,则从数据库中获取,然后将数据存储到缓存中以备后续请求使用。为了保持一致性,当数据库中的数据更新时,你需要显式地使缓存中对应的数据失效或更新,可以在数据库更新后立即删除或更新缓存中的数据。

  • 读写-通过(Read-Through,Write-Through):在这种模式下,应用程序同时向数据库和缓存读写数据。当数据库中的数据更新时,缓存中的数据也会同时更新。同样,当从缓存中读取数据时,如果不存在,就从数据库中获取,然后再存储到缓存中。这确保了数据库和缓存的数据保持一致。

  • 写入-通过(Write-Through):类似于读写-通过,但在这种方法中,当数据写入数据库时,也会立即写入缓存。然而,读取操作仍然是从缓存中进行。这有助于减少缓存未命中的次数。

  • 缓存失效(Cache Invalidation):不是在每次数据库更新时都更新缓存,你可以选择使受影响的数据缓存失效。这意味着从缓存中删除过期的数据,这样下一次读取操作将从数据库中获取最新的数据。缓存失效可以通过应用程序中的触发器或事件来实现,它们检测数据库中的更改,然后通知缓存使相应的数据失效。

  • 生存时间(Time-To-Live,TTL):你可以为缓存的数据设置过期时间。这样即使数据库发生了更新,缓存也会在一定时间后过期,然后重新从数据库获取新鲜数据。

通过采用这些策略中的一种或多种组合,你可以在应用程序中保持数据库和Redis缓存之间的一致性。每种方法都有其复杂性、性能和一致性保证方面的权衡,所以选择最适合你应用需求的策略即可。

相关推荐
夜泉_ly2 小时前
MySQL -安装与初识
数据库·mysql
qq_529835353 小时前
对计算机中缓存的理解和使用Redis作为缓存
数据库·redis·缓存
月光水岸New5 小时前
Ubuntu 中建的mysql数据库使用Navicat for MySQL连接不上
数据库·mysql·ubuntu
狄加山6755 小时前
数据库基础1
数据库
我爱松子鱼5 小时前
mysql之规则优化器RBO
数据库·mysql
chengooooooo5 小时前
苍穹外卖day8 地址上传 用户下单 订单支付
java·服务器·数据库
Rverdoser6 小时前
【SQL】多表查询案例
数据库·sql
Galeoto6 小时前
how to export a table in sqlite, and import into another
数据库·sqlite
希忘auto7 小时前
详解Redis在Centos上的安装
redis·centos
人间打气筒(Ada)7 小时前
MySQL主从架构
服务器·数据库·mysql