引言
朋友张三给我讲了一个故事,还给我简单谈了谈redis的常见面试问题以及解决思路。张三某日去一家闻名小镇的苍蝇馆子吃饭,碰巧今天小镇有活动,张三一行人见状抓紧前行...
击穿
来这家馆子吃饭的人数剧增,张三和其他饭友一样来到店里坐下,店家原本准备的土豆烧肥肠, 梅菜扣肉,凉拌三丝,黑豆花早就被一扫而空,张三和其他饭友都点了这几样菜,这时只有等待店家重新制作完成方能食用,这个现象是店家原本准备了这几样菜,但由于人数比往常剧增再加上需求都是这几样菜, 就造成了大量的食客等待,这一现象就像是数据库原本有某些key,前端访问这些缓存的key是没问题的,但突然或者某个时刻大量的key在缓存中失效了,同时有高并发的情况来访问这些key,在我们代码实现上就会去数据库查询keys并将其返回且放入缓存中, 那么在高并发情况同时多个请求去数据库定会对数据库造成压力,这一现象就可以理解为缓存击穿,总结一句话就是,击穿前提是一定有高并发,几千个几万个访问请求压过来且key过期了,直接去访问数据库了,对数据库造成了压力。
店家面对如此多的需求怎么解决,那么肯定需要排队点餐或者点餐有先后顺序,店家会一个订单接着一个订单的处理这么多食客的需求,至于厨房怎么加工,是多线程还是单线程这里不讨论,确定一点就是同一时间只处理一个,redis是单进程单实例,我们可以使用setnx() 对Key加锁,只有获得锁的线程才去访问数据库并将数据回写到缓存这样后期有其他线程来查询这个key就有缓存了,加锁也会存在锁过期而查询数据库还未返回,对于锁过期可以使用另外一个线程来监控当前线程是否取回数据,未取回就增加锁的过期时间。
雪崩
同样的情况下,我们把成品食材不足情况在恶化一下,店家由于未预料到今日食客的增加,原本准备的辣椒,土豆,食用油,Q弹肥肠,大蒜,香菜,梅菜,大片五花肉,莴笋,海带,胡萝卜等基础食材大量匮乏,食客又要在此店吃饭,那店家就只有去花时间及人力去购买这些基础食材, 这个现象是大量的食材在同一时刻匮乏,这个现象就像是在多个key在同一时刻(比如零点)发生过期,也可能是一个key有几十个访问过来加起来之后造成的对数据库的访问压力。
雪崩了怎么解决?
解决思路是先区分跟时点性有无关系,无关就用随机过期时间来解决,有关的话可以采取a:强依赖击穿的方案,就是和击穿处理方式一样,b:在业务层增加判断,零点延时这种,可能在延时的这1秒或者2秒后面就已经把数据取过来放在redis里了,这样都不用这些个请求压到数据库。
穿透
张三隔壁桌来了几个外地客,让店家做个大盘鸡和手抓排骨饭,店家可犯难了,一个川菜馆哪会做新疆菜,只好委婉让客人点店家能提供的菜品,这一现象是店家无法提供本就不会的菜品,这个现象就像是前端传给业务层一些个数据库本身就不存在的key,这就是穿透。
穿透了怎么解决?
解决思路是增加算法来控制key不走向数据库,可以自己在客户端实现过滤算法,也可用现成的过滤器比如布隆过滤器、布谷鸟过滤器。
总结
今天简单介绍了redis常见缓存面试的击穿、雪崩、穿透的现象和解决思路,我们下期再见!欢迎关注,发现更多精彩内容!