首页 > 其他分享 >缓存穿透/击穿/雪崩(附生产BUG)

缓存穿透/击穿/雪崩(附生产BUG)

时间:2024-10-17 13:48:18浏览次数:3  
标签:缓存 请求 过期 数据库 DB 雪崩 key BUG

优质博文:IT-BLOG-CN

一、背景

为什么要写这篇文章?
生产缓存生成服务转java时,需要通过配置文件进行流量切换。开发人员同时打开了两个配置页面。原配置信息=ABCDEF。在第一个配置页面进行缓存切换,添加G业务缓存,配置信息=ABCDEFG。随后H业务也需要进行缓存切换,但开发人员在第二个配置页面添加了H,配置信息=ABCDEFH导致第一次添加的G业务写缓存丢失。随着时间的推移8分钟后G业务缓存陆续过期,造成缓存雪崩

为什么保存配置和审核配置的时候没有发现异常
切流量设计10多种业务需要修改20多次配置,操作上惯性认为页面刷入是最新的版本,没有逐一进行检查。

监控为什么没有及时告警
监控比较滞后,目前监控的指标比较粗粒度,只有缓存过期后,导致订单量下降才会进行告警。同时缓存命令率的监控也是10分钟后直接掉至0

影响的单量
影响订单300单,并立即回滚配置信息。

二、缓存雪崩

大量的key设置了相同的过期时间,或者因为Redis实例宕机,在同一时刻缓存全部失效,造成请求全部穿透到DB,瞬时DB请求量大、压力骤增,可能导致DB被打挂。

解决方案:
【1】过期时间打散: 避免大量key同时过期,可以在设置过期时间时,在基础过期时间上加一个随机值来打散过期时间,通过打散过期时间,避免同一时间大量缓存过期。
【2】不过期: 不为数据设置过期时间或者设置比较长的过期时间,由专门的job应用定时刷新缓存。
【3】Redis高可用: 通过主从复制,故障转移等高可用机制避免 Redis 集群不可用导致的缓存雪崩。
【4】数据库限流与熔断: 对数据库的读添加限流与熔断机制,目的主要是为了在无可避免的缓存雪崩时保护数据库,使得之后能快速恢复缓存。
【5】数据库解耦: 应用完全与数据库解耦,只读Redis,由专门的job应用主动填充缓存。

三、缓存穿透

访问一个缓存和数据库都不存在的key,此时会直接打到数据库上,并且因为查不到数据,也不会写入缓存,所以下一次同样会打到数据库上,请求每次都会走到数据库,流量大时可能导致数据库被打挂。

解决方案:
【1】空值缓存: 查询数据库发现没有数据,给对应的key存入一个空值缓存,代表数据库中没有数据,应用查询到空值就直接返回,避免了穿透到DB的读流量。
【2】布隆过滤器:
    1、空值缓存已经能解决问题,但是在数据量非常大的情况下,我们还得考虑空间利用的高效。
    2、布隆过滤器是这样一个数据结构,它有一个初始值为0bit数组以及Nhash函数构成,它可以快速判断或标记当前值是否存在,标记的主要步骤为三个:
         ☑️ 使用Nhash函数计算的Nhash值。
         ☑️ Nhash值与bit数组取模得到N个映射的下标。
         ☑️ 将bit数组中N个下标对应的位置置为1
    3、当我们需要查询一个值时,重复上述步骤1,2得到N个下标,当这N个下标上对应的值均为1,则说明该值已被标记,否则未被标记。
    4、当然由于存在hash冲突,会存在一定的误判,所以布隆过滤器的特点是判断不存在的,则一定不存在;判断存在的,大概率存在。以存在误判的代价,换取空间利用上的高效。
【3】非法值校验: 对于一些请求参数,我们是能够判断出是否合法,如果不合法直接在入口处拦截,自然不需要穿透到DB。比如机票查询请求了一个不存在的航线,我们可以在入口校验时将该请求拦截。

四、缓存击穿

存在一个高并发读的热点key,在缓存过期的一瞬间,有大量的读请求,由于此时缓存过期了,所以请求最终都会走到数据库,造成瞬时数据库请求量大、压力骤增,可能导致数据库被打挂。

解决方案:
【1】锁:
    1、当大量请求并发读取缓存并失败时,其实只需要一个线程/机器去访问数据库并填充缓存,其他线程/机器只需等待缓存填充完成后读取缓存就行。
    2、我们可以通过互斥锁使得只有一个线程/机器能够访问数据库并填充缓存,线程间的同步比较容易,因为是在一个进程内,使用java提供的同步机制,比如ReentrantLock即可。
    3、机器间的同步,由于涉及到分布式环境,因此需要分布式锁来进行同步。简单的分布式锁可以通过Redis或者DB实现,更高级的可以通过zookeeper这样的分布式协调服务来实现。

【2】热点数据不过期: 既然缓存击穿是由热点key过期导致的,那么我们可以不为热点数据设置过期时间,而是由专门的后台job应用进行定时的刷新,在携程内部qshcedule能很好的解决我们的需求。

标签:缓存,请求,过期,数据库,DB,雪崩,key,BUG
From: https://blog.csdn.net/zhengzhaoyang122/article/details/142864927

相关文章

  • Springboot缓存+定时提交优化频繁数据库表修改
    缘起最近在弄一个答题小程序,当用户选择的时候需要把用户选择的选项提交到服务器上,然后整个字段是个json格式的,更新的方法也就是解析json后添加选项进入json中。于是其中就涉及到频繁的数据库修改,因为用户答题速度根据题目不同嘛,所以我就寻思这样频繁的修改,数据量上来速度就会受......
  • 常见的缓存淘汰算法
    应用场景:缓存淘汰算法可以广泛应用于任何有缓存淘汰需求的场景,并不仅限于某个特定的插件或工具。许多软件和系统,如数据库(Redis、Memcached)、Web服务器(Nginx、Varnish)、内容分发网络(CDN)、浏览器缓存、甚至操作系统的内存管理,都会使用这些算法来决定在缓存空间满时该移除哪些数据......
  • win11网络修改篡改bug自动修改dns没有网络问题
    1.问题描述没有网络,dns一直是自动获取的,但是在重启或连接vpp后,会被设置成某个固定值正常情况:莫名其妙的篡改:  2.解决办法1.首先,删除所有网络的手动dns配置,控制中心那个dns管理没有用,在设置中删除网络,不然问题还会出现-2.然后,进入注册表\HKEY_LOCAL_MACHINE\SYSTE......
  • 性能优化实战(三):缓存为王-面向缓存的设计
    如果你觉得这篇文章对你有帮助,请不要吝惜你的“关注”、“点赞”、“评价”、“收藏”,你的支持永远是我前进的动力~~~ 个人收藏的技术大会分享PDF文档,欢迎点击下载查看!!!本文是我在做网易考拉海购性能优化时的真实实践,希望对你也有帮助!!!一、流量走向示意图通常一个请求的......
  • CtsPermissionTestCases之android.permission.cts.DebuggableTest#testNoDebuggable
    平台:高通C6490,android13测试结果:android.permission.cts.DebuggableTest#testNoDebuggablefailjunit.framework.AssertionFailedError:Packagesmarkeddebuggable:[com.skyworthdigital.autotest.all] 这个问题是该测试对应的app是否有debugable的标签。解决......
  • Redis的缓存问题
    缓存雪崩定义:缓存雪崩是指在某个时间段内,缓存中的大量数据同时失效或者大量的请求集中到某一个时间点发生,导致数据库压力骤增,甚至引起服务崩溃的现象。原因:通常是由于缓存中的大量数据同时过期或者大量的请求集中到某一时间点。例如,如果缓存中的大量数据在同一时间点过期,那......
  • 我被 .NET8 JIT 的一个BUG反复折磨了半年之久
    很久很久没有写过博客了,正好最近园子又挣得一线生机,必须得凑个热闹水一篇.事情是这样的,在今年的早些时候,把公司的一部分api服务器的.net版本从6升级到了8,毕竟6马上就是EOL了(.NET6TLS到2024年11月12日).没成想在升级完的3个月后竟然触发了一个.NET8runtimeJIT的B......
  • bugku USB 流量截取
    url:https://ctf.bugku.com/challenges/detail/id/2416.htmlwriteup: https://blog.csdn.net/qq_26961571/article/details/136021514?spm=1001.2014.3001.5501这个题太恶心了,不过至少知道 leftovercapturedata是用于存储 LeftoverCaptureData在Wireshark中的作用是......
  • Redis缓存更新策略
    缓存更新策略内存淘汰超时剔除主动更新说明利用Redi的内存淘汰机制,当内存不足时自动淘汰部分数据,下次查询时更新缓存给缓存数据添加TTL(即缓存存在时间)的时间,到期后自动删除缓存,下次查询时更新缓存在修改数据库的同时,更新缓存一致性差一般好维护成本无低高业务使用场景:低一致......
  • redis缓存穿透、雪崩、击穿
    缓存穿透缓存穿透:客户端请求的数据在缓存和数据库都不存在。这样缓存永远不会生效,这些请求都会打到数据库中。解决方案缓存空对象(常用)优点:实现简单,维护方便缺点:额外的内存消耗;可能造成短期的不一致(可以设置TTL时间,缓解不一致的情况)布隆过滤器(常用)优点:内存占用少,没用多......