Redis学习总结---缓存问题

本文探讨了缓存与数据库数据不一致的四种现象:缓存更新与读取问题、缓存击穿、缓存穿透以及缓存雪崩。提供了先删除缓存后更新数据库的延时双删和异步串行化解决方案,以及应对击穿和穿透的互斥锁和布隆过滤器策略,还介绍了如何通过随机过期时间和分布式缓存避免雪崩。
摘要由CSDN通过智能技术生成

缓存异常有四种类型:

  • 缓存和数据库的数据不一致
  • 缓存雪崩
  • 缓存击穿
  • 缓存穿透

一、如何保证缓存与数据库双写时的数据一致性?

背景:使用到缓存,无论是本地内存做缓存,还是Redis做缓存,都会存在数据同步问题,因为配置信息缓存在内存中,而内存无法感知在数据在数据库的修改,就会造成数据库中的数据和缓存中的数据不一致的问题

针对这种现象共有四种解决方案:

  • 先更新数据库,后更新缓存
  • 先更新缓存,后更新数据库
  • 先删除缓存,后更新数据库
  • 先更新数据库,后更新缓存

  第一种和第二种没有人使用。第一种存在的问题是:并发更新数据库场景下,会将脏数据刷到缓存。第二种存在的问题是:如果先更新缓存成功,但是数据库更新失败,会造成数据不一致的问题。主要使用第三种和第四种。

1、先删除缓存,后更新数据库

此方案存在的问题:请求A(更新操作),请求B(查询操作)

  1.   请求A进行写操作,删除缓存
  2. 请求B进行查询操作,发现缓存不存在
  3. 请求B就去数据库种查询旧值
  4. 请求B将旧值写入缓存
  5. 请求A将新值写入数据库

上述会导致数据不一致的问题。如果不给缓存设置过期时间策略,该数据永远是脏数据

解决方案一:延时双删

public void write(String key,Object data){
    Redis.delkey(key);
    db.updateData(data);
    Thread.sleep(1000);
    Redis.delkey(key);
}

解决方案二:更新与读取操作进行异步串行化

异步串行化

  一个数据变更的操作,先执行删除缓存,然后更新数据库,但是在更新还没有完成的时候,如果此时有一个新的请求过来,读到了空的缓存,那么就可以先将缓存更新的请求发送到队列里,此时会在队列中积压,排在刚才更新库的操作之后,然后同步等待缓存更新完du

读操作去重

多个读库更新缓存的请求串在同一个队列中是没有意义的,因此可以做过滤

2、先更新数据库,后更新缓存

  会导致数据库更新成功了,但是缓存阶段出错了,没有删除成功,那么此时再读取缓存的时候每次都是错误的数据了。此时解决方案是利用消息队列进行删除的补偿

3、什么是缓存击穿?

是指某个热点的key失效,大量请求同时访问这个过期数据,就会造成大量请求读缓存没有读到数据,从而导致高并发访问数据库,引起数据库压力剧增

从两个方面解决:

  • 考虑热点key不设置过期时间
  • 互斥锁使访问有序

  在缓存失效后,通过互斥锁或者队列来控制读数据和写缓存的线程数量,比如某个key只允许一个线程查询数据和写数据,其他线程等待

4、什么使缓存穿透?

指的是用户请求的数据在缓存中不存在,同时数据库中也不存在,如果有恶意攻击者不断请求系统中不存在的数据,会导致短时间内大量的请求落在数据库上,造成数据库压力过大,甚至数据库承受不住而宕机崩溃

缓存穿透的关键在于在Redis中查不到key值,

解决方法:

  • 将无效的key存放进Redis中,即缓存空对象
  • 使用布隆过滤器

5、什么是缓存雪崩?

指的是大量请求缓存中大面积失效的缓存数据。

解决方案:

  • 缓存数据设置随机的过期时间,防止同一时间大量数据集合失效。
  • 集群,将数据分布在不同的缓存数据库中。
  • 限流,通过加锁或队列来控制读 数据库写缓存的线程数量

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值