缓存处理流程
缓存穿透
用户不断地像服务器发起请求,查询缓存和数据库中不存在的数据。
用户发起请求大量不存在的数据,由于缓存中不存在这样的数据,所以压力全部给到数据库,同时数据库中也不存在这样的数据,导致无法更新到缓存数据。其中,redis内部一直平稳运行。
大部分是由于恶意攻击导致的缓存穿透。
解决方案
- 对空值进行缓存。如果一个查询返回的数据为空(无论数据是否存在),我们都把这个空结果进行缓存,设置空结果的过期时间很短。
- 增加id校验。对于异常请求直接拦截(如id为负数)
- 布隆过滤器。布隆过滤器是一个高空间利用率的概率性数据结构,由二进制向量(即位数组)和一系列随机映射函数(即哈希函数)两部分组成。
布隆过滤器使用exists()
来判断某个元素是否存在于自身结构中。当布隆过滤器判定某个值存在时,其实这个值只是有可能存在;当它说某个值不存在时,那这个值肯定不存在,这个误判概率大约在 1% 左右。 - 进行实时监控。当redis中的命中率急剧降低,就开始排查问题。设置黑名单。
缓存击穿
现象:
- 数据库访问压力瞬间增大
- redis中没有出现大量key过期
- redis正常运行,数据库崩溃
缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
例如:redis中的某个key过期了,大量用户同时访问使用这个key
解决方案
- 预先设置热门数据。在redis高峰访问之前,把热门数据提前存入redis里面,加大这些热门数据的时长,避免经常过期。
- 锁。会降低效率。
缓存雪崩
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至崩溃。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是大量不同数据集中过期了,很多数据都查不到从而查数据库。
解决方案
- 构建多级缓存结构。ngix缓存+redis缓存+其他缓存。热点数据均匀分布在不同搞得缓存数据库中。
- 使用锁或者队列。造成效率极低,不适合并发较高的情况。
- 设置过期标志更新缓存。记录缓存数据是否过期(设置提前量),如果过琪会触发通知另外的线程去后台更新实际的key的缓存。
- 将缓存失效时间分散开或延长过期时间