首页 > 其他分享 >缓存异常

缓存异常

时间:2023-02-04 21:44:45浏览次数:42  
标签:缓存 过期 异常 数据库 key 淘汰 数据

缓存异常解决

这三个问题,说句实在话,一般中小型传统软件企业,很难碰到这个问题。如果有大并发的项目,流量有几百万左右。这三个问题一定要深刻考虑。

缓存击穿

缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。做类电商项目的时候,把这货就称为“爆款”。

解决方案:

其实,大多数情况下这种爆款很难对数据库服务器造成压垮性的压力。达到这个级别的公司没有几家的。所以,对主打商品都是早早的做好了准备,让缓存永不过期。即便某些商品自己发酵成了爆款,也是直接设为永不过期就好了。

(1) 从redis上看,确实没有设置过期时间,这就保证了,不会出现热点key过期问题,也就是“物理”不过期。

(2) 从功能上看,如果不过期,那不就成静态的了吗?所以我们把过期时间存在key对应的value里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建,也就是“逻辑”过期。

缓存穿透

缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存,就会每次都去查询数据库,而每次查询都是空,每次又都不会进行缓存。假如有恶意攻击,就可以利用这个漏洞,对数据库造成压力,甚至压垮数据库,导致所有的请求都怼到数据库上,从而数据库连接异常。

解决方案:

(1)利用互斥锁,缓存失效的时候,先去获得锁,得到锁了,再去请求数据库。没得到锁,则休眠一段时间重试

(2)采用异步更新策略,无论key是否取到值,都直接返回。value值中维护一个缓存失效时间,缓存如果过期,异步起一个线程去读数据库,更新缓存。需要做缓存预热(项目启动前,先加载缓存)操作。

(3)提供一个能迅速判断请求是否有效的拦截机制,比如,利用布隆过滤器,内部维护一系列合法有效的key。迅速判断出,请求所携带的Key是否合法有效。如果不合法,则直接返回。

(4) 如果从数据库查询的对象为空,也放入缓存,只是设定的缓存过期时间较短,比如设置为60秒。

缓存雪崩

缓存雪崩,是指缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。

产生雪崩的原因之一,比如商城马上就要到双十一零点,很快就会迎来一波抢购,这波商品时间比较集中的放入了缓存,假设缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力波峰。

其实集中过期,倒不是非常致命,比较致命的缓存雪崩,是缓存服务器某个节点宕机或断网。因为自然形成的缓存雪崩,一定是在某个时间段集中创建缓存,那么那个时候数据库也是可以顶住压力的,无非就是对数据库产生周期性的压力而已。而缓存服务节点的宕机,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。

解决方案:

做电商项目的时候,一般是采取不同分类商品,缓存不同周期。在同一分类中的商品,加上一个随机因子。这样能尽可能分散缓存过期时间,而且,热门类目的商品缓存时间长一些,冷门类目的商品缓存时间短一些,也能节省缓存服务的资源。

(1)给缓存的失效时间,加上一个随机值,避免集体失效。

(2)使用互斥锁,但是该方案吞吐量明显下降了。

(3)双缓存。我们有两个缓存,缓存A和缓存B。缓存A的失效时间为20分钟,缓存B不设失效时间。自己做缓存预热操作。然后细分以下几个小点

a. 从缓存A读数据库,有则直接返回

b. A没有数据,直接从B读数据,直接返回,并且异步启动一个更新线程。

c. 更新线程同时更新缓存A和缓存B。

缓存淘汰

最大内存参数

我们的redis数据库的最大缓存、主键失效、淘汰机制等参数都是通过配置文件来配置的。这个文件是我们的redis.config文件。

maxmemory <bytes>:设置最大内存

image-20201122184034973.png

内存淘汰策略

截至目前 redis 一共为我们提供了八个不同的内存置换策略。很早之前提供了6种。

image-20201122183955375.png

(1)volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。

(2)volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。

(3)volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。

(4)volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。

(5)allkeys-lru:从数据集中挑选最近最少使用的数据淘汰

(6)allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰

(7)allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

(8) no-enviction(驱逐):禁止驱逐数据,这也是默认策略。意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失。

淘汰机制的实现

既然是淘汰,那就需要把这些数据给删除,然后保存新的。

Redis 删除策略主要有以下几种:

  • 惰性删除:master节点每次读取命令时都会检查键是否超时,如果超时则执行del命令删除键对象,之后异步把del命令slave节点,这样可以保证数据复制的一致性,slave节点是永远不会主动去删除超时数据的。
  • 定时删除:Redis的master节点在内部定时任务,会循环采样一定数量的键,当发现采样的键过期时,会执行del命令,之后再同步个slave节点。
  • 主动删除:当前已用内存超过maxMemory限定时,触发主动清理策略。主动设置的前提是设置了maxMemory的值。

标签:缓存,过期,异常,数据库,key,淘汰,数据
From: https://www.cnblogs.com/yhdxx/p/17092469.html

相关文章

  • vuejs从入门到精通——计算属性缓存 vs 方法
    计算属性缓存vs方法https://cn.vuejs.org/guide/essentials/computed.html#basic-exampletemplate:<p>{{calculateBooksMessage()}}</p>js://组件中fun......
  • python基础:重要内置函数、常见内置函数(了解)、可迭代对象、迭代器对象、for循环的本质
    目录一、重要内置函数1、zip2、filter3、sorted二、常见内置函数(了解)1、abs2、all3、any4、bytes5、bin、oct、hex、int6、callable7、chr、ord8、dir9、divmod10、enumera......
  • JVM 是如何处理异常的?
    https://www.cnblogs.com/newber/p/15293184.html 今天我们来讲讲Java虚拟机的异常处理。先讲异常吧。 在Java语言规范中,所有异常都是Throwable类或者其子类......
  • Python----异常处理及模块
    异常处理当检测到⼀个错误时,解释器就⽆法继续执⾏了,反⽽出现了⼀些错误的提示,这就是所谓的"异常"。python提供了两个非常重要的功能来处理python程序在运行中出现的异常......
  • Redis 缓存穿透、缓存雪崩、缓存击穿
    Redis缓存穿透、缓存雪崩、缓存击穿 上一篇压力测试、性能优化、jvm调优下一篇缓存数据一致问题解决方案本文作者:Little_Monster-lhq本文链接:https://www.cn......
  • 全局异常处理解决重复添加同一用户-cnblog
    2.6全局异常处理2.6.1思路分析要想解决上述测试中存在的问题,我们需要对程序中可能出现的异常进行捕获,通常有两种处理方式:A.在Controller方法中加入try...catch进行......
  • 79、缓存---SpringCache---原理与不足
    /***Spring-Cache的不足:*1)读模式:*缓存穿透:查询一个null的数据;====》解决:缓存空数据:spring.cache.redis.cache-null-values=true*缓存击穿:大量并发进......
  • 78、缓存---SpringCache---@CacheEvict
    @CacheEvict(value={"catagory"},key="'OneLevelCategory'")------失效模式例如,当我们修改菜单时,就会删除catagory缓存中的OneLevelCategory缓存如果我们修改......
  • 使用Varnish部署缓存服务器
    一、Varnish介绍1、varnishVarnish是一款高性能、开源的缓存反向代理服务器。它从客户端接受请求,并尝试从缓存中响应请求,如果无法从缓存中提供响应,Varnish向后端服......
  • Redis缓存穿透、击穿、雪崩
    文章目录​​缓存穿透​​​​缓存雪崩​​​​缓存击穿​​​​代码实战部分​​​​缓存击穿实战代码封装​​​​缓存穿透解决​​Redis目前是非常流行的缓存数据库,缓存......