缓存一致性,删除缓存,写入缓存,缓存击穿,缓存穿透,缓存雪崩

一、DB操作与缓存操作一致性的问题

当你既要更新数据库,又要更新缓存的时候,就涉及到一致性的问题,如何保证两者能同时成功呢?

  1. 通过消息队列,将对缓存的操作放到队列实现,可以确保其成功。
  2. 订阅 binlog 日志,需要借助 canal 工具来知道数据库做了哪些操作,然后去操作缓存。
  3. 通过 dtm 二阶段消息,也可以确保缓存被操作成功。

二、如何删除缓存

1、先删缓存再更新数据库
  1. 线程A删除缓存,还没来得及更新数据库。
  2. 线程B进来了,发现缓存没有,读取数据库(此时是旧值),将旧值回填缓存。
  3. 线程A更新了数据库。

会出现缓存中的数据是旧值。

缓解方法

  1. 设置简短的过期时间兜底,在这个时间内会出现不一致,缺点是数据库负载会加大。
  2. 延时双删,线程A删除缓存,更新数据库,sleep一会,再删一次缓存,这个睡眠时间是个问题,所以没办法根治。
  3. 在应用层引入类似版本的机制,对应用层有要求,通用性受限,不易复用。
2、先更新数据库再删缓存
  1. 线程A更新了数据库中的值,但还没来得及删除缓存中的值。
  2. 线程B读取到缓存,此时为旧值。
  3. 线程A删除缓存。

这种情况总体对业务影响较小。一般在生产环境中,也推荐大家采用该模式。

三、如何写入缓存

  1. 线程A发现缓存为空,查询数据库,准备回填缓存的时候发生了阻塞。

  2. 线程B发现缓存为空,查询数据库,此时看到的值为新值,因为其他线程修改了数据,回填缓存。

  3. 线程A苏醒过来,回填缓存,此时是旧值。

会出现缓存中的数据是旧值。

如果要想解决这种问题,那就只能在读缓存的时候加分布式锁,当然在这个过程中可以做一些优化,具体可以使用 rockscache它的说明,具体原理图

img

四、缓存击穿

前面说到,我们应该先更新数据库,再删除缓存,那么对于热点数据,突然把缓存删了会导致缓存击穿,对数据库造成巨大冲击,针对这种情况,我们需要限制最终去到数据库的流量,我们可以在进程内部加锁,也就是单飞模式,这样每个进程只有一个查询数据库的操作,当然如果你的项目服务器很多,那么对数据库的查询也会很多,那么只能使用分布式锁来加以限制。

五、缓存穿透

如果请求的数据在数据库中也不存在,那么为了节省缓存空间一般是不会缓存它的,这就会导致这些请求都会一次次的被打到数据库,这就是缓存穿透。

首先,如果预防住了缓存击穿,那么在一点程度上也减轻了缓存穿透的危害,除此之外,我们还可以引入布隆过滤器将这些恶意的key存起来。

六、缓存雪崩

如果在某一个时刻,缓存大面积同时过期,那么这就是缓存雪崩,预防的方式也很简单,为不同的key设置不同的过期时间,过期时间最好带一个随机数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值