Redis 击穿、穿透、雪崩业务场景和解决方案

    技术2022-07-11  79

    Redis 击穿、穿透、雪崩

    业务场景:做缓存使用时 数据缓存在redis中,过滤大部分请求,实现只有少量请求达到数据库服务。给数据库减轻压力

    击穿

    原因

    给key设置了过期时间(LRU/LFU)当key过期之后,数据被清理掉了。突然来了一批访问这个Key的。这是请求就会压到数据库上Key的过期导致的高并发访问数据库,给数据库造成了压力如果过期之后,只有少量请求访问这个Key,达到数据库不能成为击穿。只有出现高并发的时候,对数据库产生影响了才叫击穿

    解决方案

    有并发时,阻止并发到达数据库,但是redis中又没有key

    redis是单进程单实例的,让访问的请求当发现key不存在的时候,使用setnx()创建一个key ,相当于向redis申请一把锁。因为setnx()只有没有这个key时,才会返回成功。所以一定只有一个请求能获得这把锁。只有获得锁的请求才允许访问数据库

    1.取key,发现没有key

    2.使用setnx()设置Key,相当于申请锁

    失败的,睡眠一会,苏醒之后重复1-2步。 如果第一步成功就能直接返回了,如果第一步失败,再次尝试setnx(),因为锁还存在,所以依然不能成功,继续进入睡眠设置key成功的请求访问数据库

    存在的问题

    死锁了,获得锁的线程挂掉了怎么办

    设置锁的过期时间当第一个挂掉后,锁过期了,会有其他的请求拿到锁。去访问数据库

    获得锁的线程没挂,但是阻塞了,因为设置的锁过期时间不够。第一个获得获得还没有取回数据,锁就被释放了,就会导致多个请求到达数据库、可能会导致部分请求延迟,丢失。 第一个从数据库获取到数据,返回了,没有获取到锁的,苏醒之后取到Key返回了 而其他获取到锁的请求,还在阻塞

    解决方案

    多线程,开启一个守护线程

    代码逻辑复杂度会提高一些

    第一个请求获取到锁之后,一个线程去数据库取数据,另一个线程监控值是不是取回来了,如果没有取回来,就更新锁时间

    穿透

    业务场景:做缓存使用时

    原因

    请求了系统中不存在的数据,自然在redis中查找不到key,从而请求达到数据库,进行数据库查询

    解决方案

    使用布隆过滤器,三种方式

    在客户端实现布隆的算法,和存储数据 则请求不到达redis,和数据库在客户端中实现布隆过滤器的算法,数据存储在redis中。redis集成布隆过滤器

    缺点:布隆过滤器只能增加,不能删除

    当业务数据会出现删除,修改的时候。使用布隆过滤器会出现问题替代方案:布谷鸟过滤器

    雪崩

    业务场景:做缓存使用时

    原因

    和击穿比较像,同一时间大量的key值过期 例如:晚上12点大量的Key需要进行更新。 导致这些key的请求如果在这时发生,则会出现大量的请求到达数据库。

    解决方案

    当业务层面数据必须在同一时间大量进行更新时

    强依赖击穿方案,让请求进行排队。只让少量的请求达到数据库定时更新,如果大部分的数据都需要在12点进行更新时,则每晚11:50至12:10分让业务暂停使用。时间可以根据时间情况控制

    当业务层面对数据更新时间没有要求时

    Key值过期时间均匀分布 -
    Processed: 0.014, SQL: 9