公司给别人做的网站违法吗,有哪些开发网站公司,罗阳网站建设,电子商务平台内经营者享有公平交易的权利老生常谈问题之什么是缓存穿透、缓存击穿、缓存雪崩#xff1f;举个例子你就彻底懂了#xff01;#xff01; 缓存穿透发生场景解决方案 缓存击穿解决方案 缓存雪崩发生场景解决方案 总结三者区分三者原因三者解决方案 想象一下#xff0c;你开了一家便利店#xff0c;店里… 老生常谈问题之什么是缓存穿透、缓存击穿、缓存雪崩举个例子你就彻底懂了 缓存穿透发生场景解决方案 缓存击穿解决方案 缓存雪崩发生场景解决方案 总结三者区分三者原因三者解决方案 想象一下你开了一家便利店店里有各种各样的零食。
这些零食在货架上而他们就是你店铺的“缓存”你的仓库则相当于“数据库”。平时当顾客来买零食时你都会从店里的货架缓存拿给他这样既快又方便。
首先让我们来看一下最常见的缓存模式 有一天你的店遇到了三种麻烦。
缓存穿透
有个顾客跑来问你“请问你们有卖最近 香香甜甜脆脆糕 吗” 你一下子懵了因为你知道货架缓存上根本没有这种东西数据不存在 但顾客不死心一直缠着你要。于是只好跑到仓库数据库去查一下结果当然是没有。
这种情况就相当于“缓存穿透”顾客的请求没有在缓存中找到只好直接访问数据库而数据库又没有这个数据。
如果此时有大量的顾客都冲进你小小的便利店向你要 香香甜甜脆脆糕 大量的请求挤进了仓库数据库那你的仓库就被挤爆了
发生场景
缓存穿透发生一般有两种情况
业务误操作缓存中的数据和数据库中的数据被误删了导致数据和数据库中都没有这项数据 比如你家小朋友备着偷偷吃掉了所有的香香甜甜脆脆糕 黑客恶意攻击故意大量访问某些读取不存在的业务 比如有个老黑粗问你这里有没有 AK47自动步枪 os??? 解决方案
应对缓存穿透常见有如下四种解决方案
非法请求限制缓存默认值或空值使用布隆过滤器来快速判断数据是否存在避免通过查询数据库来判断数据是否存在限流策略
第一种方案非法请求限制 在便利店入口处就设置一个身份系统检测你起码得有个合法身份 当有大量的恶意请求访问不存在的数据的时候也会发生缓存穿透 因此我们最好在 API 入口处就判断请求参数是否合理比如说 请求参数是否含有非法值请求字段是否存在如果判断出是恶意请求就直接返回错误避免进一步访问缓存和数据库
第二种方案缓存默认值或空值 没有 香香甜甜脆脆糕 那就拿个绿豆糕给你 针对查询的数据在缓存中设置一个设置一个空值或者默认值这样后续请求就可以从缓存中读取到空值或者默认值返回给应用而不会继续查询数据库
但是这里存在一个问题如果攻击者每次都用不同的且不存在的 key 来请求数据那么这个方案就会丧失它的效果而且要回写特殊值会浪费不少 Redis 内存这可能会导致 Redis 内存不足执行淘汰策略的时候把其他有用的数据淘汰掉。
第三种方案使用布隆过滤器 在货架缓存和仓库数据库之间放置一个智能查询机布隆过滤器他能快速判断数据是否存在 我们在写入数据库数据时使用布隆过滤器做个标记然后在用户请求到来时业务线程确认缓存失效后通过查询布隆过滤器快速判断数据是否存在如果不存在就不用通过查询数据库来判断数据是否存在了
但是值得注意的是布隆过滤器说数据存在并不一定证明数据库中存在这个数据但是查询到数据不存在数据库中一定就不存在这个数据。这涉及到布隆过滤器的工作原理放在以后的文章中进行讲述
第四种方案限流策略 门口设置保安你们这些要 香香甜甜脆脆糕 的得排队 针对频繁请求的特定数据可以设置限流策略 例如使用令牌桶算法或漏桶算法限制对这些数据的请求频率减轻数据库的压力
缓存击穿
有一天店里的一包薯片突然成了热门商品热点数据大家都想要买。但这包薯片刚好快过期了于是你把它的货架撤下来热点数据过期。可是就在这时一大群顾客蜂拥而至每个人都想要这包薯片大量请求访问热点数据。你只好一个个去告诉他们“薯片没有了换新的了。”结果这些顾客都不信非得一个个去仓库看有没有。这样一来你的仓库数据库就被大量请求冲击差点瘫痪。
如果缓存中的某个热点数据过期了而此时大量的请求访问了该热点数据就无法从缓存中读取直接访问数据库数据库就很容易被高并发请求冲垮
注意缓存击穿的关注点是热点数据不存在缓存上因为如果是普通数据那就是正常的缓存未命中而已反之热点数据如果没命中就容易导致大量的请求落到了数据库上
解决方案
应对缓存击穿常见有如下四种解决方案
设置热点数据的热度时间窗口设置缓存永不过期使用互斥锁或者分布式锁异步更新缓存
第一种方案设置热点数据的热度时间窗口 零食快过期了我直接延长你保质期 对于热点数据可以设置一个热度时间窗口在这个时间窗口中如果一个数据被频繁访问就将其缓存时间延长避免频繁刷新缓存导致缓存击穿
第二种方案使用互斥锁或分布式锁 只准一个人冲进仓库去找 保证同一时间只有一个业务线程更新缓存未能获取到互斥锁的请求要么等待锁释放后重新读取缓存要么就返回空值或者默认值
实现互斥锁的时候最好设置超时时间不然第一个请求拿到了锁然后这个请求发生了某种意外而一直不阻塞一直不释放锁这是其他请求也一直拿不到锁整个系统就会出现无响应的现象
分布式锁的问题可以看看这篇文章 Redis原理篇——分布式锁
第三种方案缓存永不过期 没错我们的食物没有保质期这一说你见过矿泉水有保质期吗你见过二锅头有保质期吗 对于一些热点数据可以将其缓存设置为永不过期避免缓存击穿
第四种方案异步更新缓存 专门雇了个店员每天检查食物保质期并更换货架食物和仓库食物不需要我操心~ 不给热点数据设置过期时间使用一个后台线程去检测缓存是否失效如果失效了就去更新缓存属于主动更新缓存的方式相比缓存失效之后遇到了大量请求被动更新的方式可以避免高峰期的缓存失效而引发的性能问题
缓存雪崩
有一天你发现货架上有一批同时进货的零食比如说薯片奥利奥妙妙脆都到了过期时间就把他们都下架了。结果第二天来了大量的顾客一个要薯片一个要奥利奥一个要妙妙脆然后货架缓存上都没有于是全部的顾客冲进了你的仓库数据库直接就把你仓库数据库挤爆了
当大量缓存数据在同一时间过期 或者 Redis 故障宕机货架坏了食物也没法吃了时如果此时有大量的用户请求都无法在 Redis 中处理于是全部请求都直接访问数据库从而导致数据库的压力骤增严重的会造成数据库宕机从而形成一系列连锁反应造成整个系统崩溃这就是缓存雪崩的问题。
发生场景
场景1缓存集中失效。比如为了双十一将一批商品放入到缓存中设置两小时过期凌晨2点过期了导致对这一批商品的访问都落到了数据库数据库就会产生压力波峰。场景2:当然缓存雪崩一个最严重特殊情况是在流量高峰一个缓存节点直接出现问题甚至扩大到缓存集群出现问题那么就会导致本应该访问缓存的流量透传到数据库上。
解决方案
可以看到发生缓存雪崩有两个原因 大量数据同时过期 Redis 故障宕机 不同的诱因应对的策略也会不同。
针对 大量数据同时过期
设置缓存数据的随机过期时间分布式锁或互斥锁数据预热后台更新缓存数据库优化
第一种方案设置缓存数据的随机过期时间 如果要给缓存数据设置过期时间应该避免将大量的数据设置为同一个过期时间我们可以给缓存数据设置过期时间时加上一个随机数这样就保证数据不会再同一时间过渡
第二种方案分布式锁或互斥锁 与缓存击穿一样保证同一时间只有一个业务线程更新缓存未能获取到互斥锁的请求要么等待锁释放后重新读取缓存要么就返回空值或者默认值 当然最好设置超时时间
第三种方案数据预热 在系统启动或者非高峰期时提前将热点数据加载到缓存中这样即时在高并发时也能够从缓存中获取到数据减轻数据库的压力
第四种方案后台更新缓存 与缓存击穿一样将更新缓存的工作交由后台线程定时更新
第五种方案数据库优化 除了缓存层面的应对策略还可以从数据库层面进行优化如提升数据库性能、增加数据库的容量等以应对大量请求导致的数据库压力
针对 Redis 故障宕机 针对 Redis 故障宕机而引发的缓存雪崩问题常见的应对方法有下面这几种
服务熔断或请求限流机制构建 Redis 缓存高可靠集群
第一种方案服务熔断或请求限流机制 一个都别进仓库了服务熔断 好吧就放几个进去哈请求限流 因为 Redis 故障宕机而导致缓存雪崩问题时我们可以启动服务熔断机制暂停业务应用对缓存服务的访问直接返回错误不用再继续访问数据库从而降低对数据库的访问压力保证数据库系统的正常运行然后等到 Redis 恢复正常后再允许业务应用访问缓存服务。
服务熔断机制是保护数据库的正常允许但是暂停了业务应用访问缓存服系统全部业务都无法正常工作
为了减少对业务的影响我们可以启用请求限流机制只将少部分请求发送到数据库进行处理再多的请求就在入口直接拒绝服务等到 Redis 恢复正常并把缓存预热完后再解除请求限流的机制。
第二种方案构建 Redis 缓存高可靠集群
服务熔断或请求限流机制是缓存雪崩发生后的应对方案我们最好通过主从节点的方式构建 Redis 缓存高可靠集群。
如果 Redis 缓存的主节点故障宕机从节点可以切换成为主节点继续提供缓存服务避免了由于 Redis 故障宕机而导致的缓存雪崩问题。
主从架构可以看看之前写的这篇文章哈
Redis实战篇——搭建主从复制
总结
三者区分
注意要区分好缓存穿透、缓存击穿和缓存雪崩三者之间的区别
缓存穿透顾名思义“穿” 了缓存“透” 了数据库数据既不存在缓存中也不存在数据库中
缓存击穿主要针对的是一个热点数据他不存在于缓存导致大量的请求访问数据库
缓存雪崩主要针对的是一批热点数据他们不存在于缓存导致大范围的数据请求访问数据库
三者原因
缓存穿透的原因呢一方面可能是黑客恶意攻击另一方面可能是业务失误把数据删除了
缓存击穿的原因呢主要就是热点数据过期了
缓存雪崩的原因呢一方面可能是大量数据缓存中过期另一方面是缓存直接宕机了
三者解决方案
针对各自的原因采取相应的方案 对于缓存穿透可以限制非法请求回写特殊值空值或默认值使用布隆过滤器
对于缓存击穿 针对热点数据可以设置过期时间延长或者直接设置为永不过期 针对缓存更新可以在失效时使用互斥锁或者后台去更新缓存
对于缓存雪崩 针对大量数据同时过期可以像缓存击穿一样互斥锁后台更新缓存或者随机设置过期时间 也可以预热数据甚至直接优化数据库 针对缓存故障采取服务熔断或者请求限流机制也可以直接搭建高可用集群