高并发 - 缓存问题处理方案

高并发 - 缓存问题处理方案

  • 原文地址:
  • 原文作者:
  • 本文永久链接:
特别说明

当前文章内容迁移中,如有问题,请提交 issues 谢谢~~

特别说明

当前文章内容迁移中,如有问题,请提交 PR 谢谢~~

一. 缓存雪崩

定义:

可能是因为数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。

解决方案

  1. 均匀分布 key 的过期时间。防止同一时间 key 大面试失效

2 种策略(同时使用):

1) .对缓存做高可用,防止缓存宕机
  • 分析用户行为,然后失效时间均匀分布。或者在失效时间的基础上再加1~5分钟的随机数。
2). 使用断路器,如果缓存宕机,为了防止系统全部宕机,限制部分流量进入 DB,保证部分可用,其余的请求返回断路器的默认值。
  • 加锁计数(即限制并发的数量,可以用 semphore)或者起一定数量的队列来避免缓存失效时大量请求并发到数据库。但这种方式会降低吞吐量。
  1. 按照 key 加锁,同一时间只允许一个请求去读库。

二. 缓存穿透

定义:

用户查询一个不存在的 key,redis 没有,请求打到缓存中。
  1. 如果查询数据库也为空,直接设置一个默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库。设置一个过期时间或者当有值的时候将缓存中的值替换掉即可。
  2. 可以给key设置一些格式规则,然后查询之前先过滤掉不符合规则的Key。
  3. 如果查询数据库也为空的时候,把这个 key 缓存起来,这样在下次请求过来的时候就可以走缓存了。当然这种方案有个弊端,那就是请求过来的 key 必须大部分相同,如果受到攻击的话,每次的 key 肯定不是固定的,只要不固定 key,这个方案就没用。
  4. 可以用缓存 key 的规则来做一些限制,当然这种只适合特定的使用场景,比如我们查询商品信息,我们把商品信息存储在 Mongodb 中,Mongodb 有一个 _id 是自动生成的,它有一定的生成规则,如果是直接根据 id 查询商品,在查询之前我们可以对这个 id 做认证,看是不是符合规范,当不符合的时候就直接返回默认的值,既不用去缓存中查询,也不用操作数据库了。这种方案可以解决一部分问题,使用场景比较少。
  5. 利用布隆过滤器来实现对缓存 key 的检验,需要将所有可能缓存的数据 Hash 到一个足够大的 BitSet 中,在缓存之前先从布隆过滤器中判断这个 key 是否存在,然后做对应的操作
    d

    三. 缓存击穿

定义:

如果网站并发访问高,一个缓存如果失效,可能出现多个进程同时查询DB,同时设置缓存的情况,如果并发确实很大,这也可能造成DB压力过大,还有缓存频繁更新的问题
  1. 对缓存查询加锁,如果 KEY 不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询。

四. 缓存预热

目的就是在系统上线前,将数据加载到缓存中。解决思路

  1. 数据量不大的话,在系统启动的时候直接加载。
  2. 自己写个简单的缓存预热程序。

五. 缓存算法

  1. FIFO算法:First in First out,先进先出。原则:一个数据最先进入缓存中,则应该最早淘汰掉。也就是说,当缓存满的时候,应当把最先进入缓存的数据给淘汰掉。
  2. LFU算法:Least Frequently Used,最不经常使用算法。
  3. LRU算法:Least Recently Used,近期最少使用算法。
  4. LRU和LFU的区别。LFU算法是根据在一段时间里数据项被使用的次数选择出最少使用的数据项,即根据使用次数的差异来决定。而LRU是根据使用时间的差异来决定的

参考文章

http://c.biancheng.net/view/5555.html

-Redis 缓存读写策略设计及常见问题

Prev:
gitkeep 文件作用
Next:
机器学习算法 - 深入理解 Embedding
Contents of this article
Contents of this article