缓存雪崩、缓存击穿、缓存穿透 ———Sidfate
今天我们讲讲用redis缓存时容易遇到的一些问题。首先要明确一点的是,缓存雪崩、击穿、穿透这些名词虽然是针对缓存的,但是实际的受害方往往是数据库(存储层)。因为我们之所以用缓存,就是为数据库服务,也就是缓存的抗压性要大于数据库,当我们缓存由于一些原因使用不当时,就会导致数据库压力剧增,由此产生上面的几种问题。
题外话:我觉得一些技术上的专有名词很扯,有些是某位大神直接自己翻译过来传开的,其实它的本意可能翻译的并不准确。所以终归到底,专有名词能记住最好,有装逼的资本;没记住也没必要强记,理解含义和场景是正解,同时面对面试官先下手为强,避免忘记名词时的尴尬。
雪崩
缓存雪崩往往是指在一段时间内,灭霸打了个响指,缓存大批量的失效(同一时间过期),没有缓存怎么办,当然就去数据库找数据了,如果请求量很大,数据库马上就崩了,由此就叫做缓存导致的雪崩。
缓存雪崩的英文原意是 stampeding herd(奔逃的野牛),指的是缓存层宕掉后,流量会像奔逃的野牛一样,奔向后端存储。
这种场景的解决方案就是给失效时间设置一个随机数:
setRedis(Key,value,time + Math.random() * 10000);
或者设置热点数据永远不过期,更新数据后更新缓存就好了。
击穿
击穿跟雪崩类似,缓存雪崩是因为大面积的缓存失效,使数据层压力剧增,而缓存击穿不同的是指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。
解决方法:使用锁机制 让其他请求进不来。使用原子性setNx
穿透
如果你看了前面的2个,缓存穿透也很好理解,都说穿透了,其实也就是缓存没数据,数据库也没数据,关键请求量还很大,你说气不气。穿透其实很可能是来自于攻击,指的是专门大批量的去请求不存在的数据,例如id是-1的数据。
简单的解决方案就是判断id的值范围,判断id≤1直接return了。当然id只是一个例子,其实针对客户端过来的参数,永远保持不信任的状态,给予合理的判断减少潜在的数据库压力是个好习惯。