注:此文不讲解最佳实践方案,只为能让刚入门的兄弟们能快速了解,如有错误的地方还请指出
在这里将用户发送的请求比喻为一颗炮弹,redis为由一堆数据组成的城墙,而mysql为目标仓库,仓库里面存的是抵挡炮弹的材料,用户和系统之间无时无刻都在进行攻防游戏。
正常的操作都是请求如果命中缓存就能快速返回结果,否则就要等mysql来返回相应数据并插入到缓存中(日常的炮弹攻防演练)。
缓存穿透(redis和数据库都没有数据)
城墙本身没有问题,采用的防护材料是made in 仓库的(缓存里面存的数据是在数据库数据的范围内的),但是用户如果不讲武德把炮弹换了个特殊材料,连仓库都没有任何防护材料能抵挡住,次次都能射穿城墙,没办法靠城墙拦截并返回一定的数据(无论如何都无法命中缓存,直接打到数据库)。
按理来说发现城墙有漏洞,仓库应该及时送上相应的防护材料堵住升级城墙(从mysql获取数据插入到redis缓存中),但是发现仓库里面根本没有相应的材料能堵上(mysql中没有相应的数据),只能任由炮弹不停轰炸,最后把仓库炸崩了。
原因:
1. 群众里面出现了坏人,发现了城墙的漏洞,铁了心要搞崩仓库(恶意攻击数据库)。
2.没人要求用户使用的炮弹规格,导致用户可能使用了城墙接不住的炮弹(没有做相应的限制用户行为的措施,导致用户可能会不断发出错误请求)。
措施:
1.掏出坚不可摧的基岩堵住炮弹缺口,但是万一仓库有材料了,可能不会及时把基岩换下来(用null值来表示不存在的key,插入相应的redis缓存)。
2.找一个“砖家”来判断这个炮弹是否合格,不合格的一律阻止炮弹通过(使用布隆过滤器),“砖家”说这个炮弹不合法就是一定不合法,但是他说合法的时候就不一定了,有时也会误判把普通炮弹给拦下来(布隆过滤器有一定概率误判),解决方案就是找个脑容量更大一点的“砖家”(将过滤器的数组大小再搞大一些)。
缓存击穿(redis没有,数据库有)
这次城墙整体是正常了,但是在日常的炮弹攻防演练过程中,突然负责守门的门卫看到自己下班到点了,然后就马上溜了,所在位置就没人看守了(缓存过期数据失效),然后刚好有一堆炮弹打到了这个缺口,一瞬间给仓库炸崩了(瞬时用户请求给数据库搞宕机了)。
原因:
门卫看到到点就准时下班了(缓存直接过期)。
措施:
1.跟门卫说是先加班一会,加班到啥时候看情况(设置逻辑过期)
2.下班到点的时候,两个门卫小心翼翼的进行交接,以防给对面炮弹钻空子(分布式锁)
缓存雪崩
有两种情况:
1.这回不是一个门卫的问题了,一堆门卫的下班点是同一时候,结果这回大片范围都没人守了(同一时间大量请求同时过期),大量的炮弹直接轰炸到仓库给炸崩了。
2.城墙因为一些天时地利人和,突然有一面塌了(redis服务器宕机),大量的炮弹直接轰炸到仓库给炸崩了。
原因:
如上情况。
措施:
1.对门卫改成弹性下班时间,每个人都得在下班后随机时间下班,不要突然空出一片没人守(设置随机过期时间)
2.城墙一面不够,那就再多造几面呗,主打的就是力大砖飞(搭建redis集群,防止单个节点出幺蛾子影响服务器)