持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
redis的异常场景类型:
在实际生产环境中有时会遇到缓存穿透、缓存击穿、缓存雪崩等异常场景,为了避免异常带来巨大损失,我们需要了解每种异常发生的原因以及解决方案,帮助提升系统可靠性和高可用。
一、缓存穿透。
什么是缓存穿透?
缓存穿透是指用户请求的数据在缓存中不存在即没有命中,同时在数据库中也不存在,导致用户每次请求该数据都要去数据库中查询一遍,然后返回空。
解决方案:
1、参数合法性校验
如果是有意义的参数值,进行合法性校验(比如手机号码),防止恶意攻击。
2、布隆过滤器
布隆过滤器(Bloom Filter,简称BF)是一种空间效率高的概率型数据结构。布隆过滤器专门用来检测集合中是否存在特定的元素。把所有数据加载布隆过滤器中,交由布隆过滤器判断处理。
布隆过滤器底层使用bit数组存储数据,该数组中的元素默认值是0。布隆过滤器第一次初始化的时候,会把数据库中所有已存在的key,经过一些列的hash算法(比如:三次hash算法)计算,每个key都会计算出多个位置,然后把这些位置上的元素值设置成1。
有关布隆过滤器的问题,后续会有专门的文章讲解。
3、返回空对象
当缓存未命中,查询持久层也为空,可以将返回的空对象写到缓存中,这样下次请求该key时直接从缓存中查询返回空对象,请求不会落到持久层数据库。为了避免存储过多空对象,通常会给空对象设置一个过期时间。
二、缓存击穿。
什么是缓存击穿?
缓存击穿,是指一个key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个屏障上凿开了一个洞。
解决方案:
1、使用互斥锁(mutex key)
让一个线程回写缓存,其他线程等待回写缓存线程执行完,重新读缓存即可。
2、热点数据不设置过期时间,或者通过异步线程进行失效时间的续期。
三、缓存雪崩。
什么是缓存雪崩?
缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,请求直接落到数据库上,引起数据库压力过大甚至宕机。和缓存击穿不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
解决方案:
1、加互斥锁
跟缓存击穿解决思路一致,同一时间只让一个线程构建缓存,其他线程阻塞排队。
2、缓存永不过期
跟缓存击穿解决思路一致,缓存在物理上永远不过期,用一个异步的线程更新缓存。
3、缓存均匀过期
设置不同的缓存失效时间,尽量做到均匀分布,随机分布,不能再同一个时间设置大量失效key,也不能再业务高峰时期,失效大量key,尽量避免。
四、缓存预热
缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统,这样就可以避免在用户请求的时候,先查询数据库,然后再将数据回写到缓存。
缓存预热的操作方法:
当数据量不大的时候,工程启动的时候加载数据到缓存;
当数据量大的时候,可以通过定时脚本,进行缓存的刷新。
五、缓存降级
缓存降级是指缓存失效或缓存服务器挂掉的情况下,不去访问数据库,直接返回默认数据或访问服务的内存数据。