缓存击穿与缓存雪崩

刷帖子,看到有佬吐槽:某个业务缓存数据到期了本来只需要删除这个业务的数据就可以,但是同事把所有缓存数据都删除了,造成数据库宕机……有回复提到缓存击穿缓存雪崩,于是就去查了资料,之前只是听说,也不知道具体是什么以及解决方法。

缓存击穿

概念

定义: 缓存击穿是指在高并发访问的情况下,某个非常热点的数据突然过期,导致大量请求在缓存中找不到数据,从而直接访问数据库,造成数据库压力瞬间增大。

发生原因

  • 热点数据过期。
  • 高并发访问热点数据。

影响

  • 数据库承受大量突发请求,可能导致性能问题。

侧重点: 缓存击穿侧重于单个热点数据的缓存失效问题。

Redis示例: 假设有一个热点商品信息缓存在Redis中,设置了过期时间。当商品信息过期时,如果有大量用户同时访问该商品,由于缓存失效,这些请求会直接穿透到数据库。

总结

  • 影响范围:缓存击穿主要影响单个热点数据。当这个热点数据在缓存中过期或不存在时,所有访问该数据的请求都会直接穿透到数据库,造成数据库的瞬时高负载。
  • 场景:通常发生在单个非常热门的缓存项上,例如,一个热门商品的详细信息、一篇热门文章的内容等。
  • 后果:虽然数据库压力增大,但通常仅限于特定的数据查询,影响相对有限。

解决方法

  1. 互斥锁:确保同一时间只有一个请求去数据库查询并更新缓存。
  2. 异步更新缓存:在缓存未命中后,异步地将数据库查询结果更新到缓存中。
  3. singlefilghtsinglefilght是 Go 标准库的包,可以确保对于同一资源的多个并发请求,实际上只有一个请求会去执行数据库查询,其他请求会等待这个查询完成,然后共享结果
  4. 永不过期:为缓存数据设置较长的过期时间或永不过期,通过后台定时任务来更新缓存。
  5. 双重检查锁定:在互斥锁内部再次检查缓存,以避免不必要的数据库查询。

常用解决方法的优劣

互斥锁(Mutex)

性能

  • 优点:在低并发情况下,性能开销较小。
  • 缺点:在高并发情况下,可能会导致大量请求阻塞,等待获取锁,从而增加延迟。

其他方面

  • 线程安全:可以保证同一时间只有一个请求执行数据库查询。
  • 复杂度:实现相对简单,但需要正确处理锁的获取和释放,以避免死锁。

异步更新缓存

性能

  • 优点:可以减少请求的等待时间,因为主请求不需要等待数据库查询完成。
  • 缺点:可能会创建大量goroutines,特别是在高并发情况下,这可能导致资源浪费和管理开销。

其他方面

  • 响应时间:主请求可以快速返回,但可能需要等待缓存更新完成才能获取最新数据。
  • 实现复杂度:需要管理异步操作和可能的并发问题。

singleflight

性能

  • 优点:在处理高并发请求时,可以显著减少对数据库的重复查询,从而减少数据库的压力和响应时间。
  • 缺点:第一个请求需要等待数据库查询,所有后续请求也会因此等待,这可能会增加延迟。

其他方面

  • 资源利用:相比于异步更新,singleflight 可以减少goroutines的创建,因为它只执行一次数据库查询。
  • 去重:自动处理了对同一资源的重复请求,减少了不必要的数据库查询。
  • 实现复杂度:使用简单,只需调用Do方法,但需要理解其工作原理。

综合比较

  1. 性能
    • 互斥锁在高并发下可能导致性能瓶颈。
    • 异步更新可以提高响应速度,但可能增加系统资源的使用。
    • singleflight 在减少数据库压力方面表现优秀,但可能会增加第一个请求的延迟。
  2. 资源使用
    • 互斥锁的资源使用相对较低。
    • 异步更新可能需要更多的goroutines和内存。
    • singleflight 在资源使用上比异步更新更高效。
  3. 可靠性
    • 互斥锁和singleflight都可以提供较为可靠的保证,确保数据库不会被重复查询。
    • 异步更新可能需要额外的逻辑来处理缓存更新失败的情况。
  4. 适用场景
    • 互斥锁适用于并发量不是特别高的场景。
    • 异步更新适用于对响应时间有较高要求的场景。
    • singleflight 适用于需要减少数据库重复查询的场景,特别是当数据库查询开销较大时。

在选择解决方案时,应根据具体场景和需求进行权衡。例如,如果数据库查询非常耗时且并发量高,singleflight 可能是更好的选择。如果并发量适中,且对延迟敏感,互斥锁或异步更新可能更合适。

缓存雪崩

概念

定义: 缓存雪崩是指缓存系统中的大量缓存数据在同一时间失效,导致大量请求直接访问数据库,造成数据库压力急剧上升,甚至导致数据库崩溃。

发生原因

  • 大量缓存设置了相同的过期时间。
  • 缓存服务器出现问题(如Redis服务宕机)。

影响

  • 大量缓存同时失效,导致数据库压力剧增。
  • 可能会导致整个系统的服务不可用。

侧重点: 缓存雪崩侧重于大量缓存同时失效的问题。

Redis示例: 如果Redis中缓存了大量数据,并且这些数据的过期时间都是相同的(例如,都在午夜12点过期),那么在过期时间到来时,会有大量数据同时失效,导致大量请求直接访问数据库。

总结

  • 影响范围:缓存雪崩影响的是整个缓存系统。当大量缓存数据几乎同时过期,或者缓存服务本身出现故障时,所有依赖于缓存的请求都可能直接访问数据库,导致数据库压力急剧上升。
  • 场景:可能发生在缓存数据的过期时间配置不当,或者缓存服务器出现故障时。
  • 后果:由于影响的是所有缓存数据,可能导致整个系统范围内的服务不可用,影响范围广泛。

解决方法

  1. 避免相同过期时间:为缓存数据设置不同的过期时间,避免大量缓存同时失效。
  2. 缓存集群:使用Redis集群来提高缓存系统的可用性。
  3. 熔断、限流:实施熔断和限流机制,保护数据库不被大量请求压垮。
  4. 备份缓存:在主缓存失效时,使用备份缓存来提供服务。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇