缓存雪崩
缓存雪崩是指存储在缓存里面的大量数据,在同一时刻全部过期,大部分流量直接到达了数据库,导致数据库压力增加,造成数据库崩溃的情况。
缓存雪崩的解决方案如下:
- 每个缓存的key设置不同的过期时间
- 采用多级缓存策略,使用Redis+Memcache组合进行缓存
- 配置服务的限流措施
缓存穿透
缓存穿透是指在短时间内有大量缓存中不存在的Key请求到数据库,增加了数据库的压力。这个场景的核心问题是针对缓存的一种攻击行为,请求的Key不仅不存在于缓存中,甚至不存在于数据库中,这种类型的Key长时间的大量的到达数据库,造成了数据库崩溃的情况。
缓存穿透的解决方案如下:
- 把无效的Key也保存在Redis里面,并且设置默认值,比如设置为null。这样第一次请求查询不到的时候,就会把Key写到缓存中,第二次请求就不会到达数据库。
- 如果攻击者不断用随机的不存在的Key攻击数据库,那么还是会存在缓存穿透的问题。那么我们就需要想一个办法,在第一次请求的时候就识别出无效的Key,在请求Redis和DB前就识别出来,如果不存在就直接返回。那么我们是否可以提前把全部数据存储在缓存中,比如用Set存储?答案是否定的,因为如果有几亿条数据,甚至更多,那么缓存肯定是无法容纳的。这时我们就需要使用布隆过滤器了。
布隆过滤器
布隆过滤器是一个用来检查一个Key是否存在的数组,它采用了bitMap存储数据,长度为m,仅包含0和1,初始化时默认值都为0,表示数据不存在。它的特点是:
- 占用空间少
- 判断Key存在的时候,Key不一定存在,但是判断Key不存在的时候,Key一定不存在
- 可以添加Key,到那时不能删除Key,因为删除Key会增加误判率
当我们往布隆过滤器里面添加数据时,为了避免地址冲突,我们会使用多个hash函数对Key进行hash运算,算得一个数值,然后对数组长度进行取模运算的到一个下标位置,每个hash值取模运算会得到不同的下标位置,把每个位置都设置为1,就完成了添加数据的操作。
当我们查询Key的时候,会先把Key用多个不同的hash函数进行hash运算,再对数组长度尽心取模运算得到多个下标位置。如果结果都是1,表示Key有可能存在;如果有一个为0,则这个Key一定不存在。
为什么说是有可能存在?
因为这些位置的1可能是其他Key存在导致的,也就是存在hash冲突的可能。由此可见,布隆过滤器只能判断Key一定不存在的情况,如果判断Key存在的情况,还是有可能直接到达数据库的,所以布隆过滤器会大幅降低缓存穿透的可能,但并不会完全解决。
为什么Key不能删除?
因为hash冲突,所以某个下标位置可能是其他Key的存在导致的,如果删除了这个下标位置,那么查询别的Key的时候,可能会导致查询失败。