Redis适用于哪些场景?
- 缓存
- 分布式锁
- 降级限流
- 消息队列
- 延迟消息队
说一说缓存穿透
缓存穿透的概念
用户频繁的发起恶意请求查询缓存中和数据库中都不存在的数据,查询积累到一定量级导致数据库压力过大甚至宕机。
缓存穿透的原因
比如正常情况下用户发起一个请求根据某个主键ID获取数据库信息,服务器接收到请求后会先查询缓存,如果缓存命中则返回,未命中就去查询数据库,数据库中存在则返回并存入Redis,不存在提示或者报错。
但是假如有人使用一定不存在的ID,比如负数或者很大的数值进行恶意频繁的请求,就会导致数据库的压力增大甚至宕机。
缓存穿透的解决方案:
- 在缓存中给不存在的ID设置null值。
对于那些缓存中和数据库中都查不到的数据,同样把它保存到缓存中并将value值设置为null,这样下次同样的id再来请求就直接从缓存中获取null值并返回。
优点:实现简单。
缺点:浪费内存,并且如果攻击者每次使用的是不同的脏数据进行攻击,这种方式是处理不了的。
- 使用布隆过滤器
使用布隆过滤器服务器的逻辑就会变成这样:
什么是布隆过滤器呢?
先来看下面这张图:
布隆过滤器的底层是一个bitmap,也就是一个数组,每个下标只存储0或1,默认初始化时全部都为0。可以在其中定义多个不同的哈希函数对要存储的数据进行计算,不同的哈希函数计算出的结果作为数组的下标将其对应的值改为1。这样不管是存数据还是查询数据都可以通过哈希计算得到对应下标然后根据是否为1判断是否存在,如果有一个值不为1则就是不存在。
但是,这种机制也是会出现一定的误判率的,具体看下面这张图:
首先将id1和id2存入布隆过滤器中,得到了对应的下标并设置为1,这个时候id3也要存进来,然后通过哈希计算得到了3、9、12的下标,这个时候虽然id3并不存在,但是布隆过滤器也会判定为存在!这个就是误判。
说一说缓存击穿
缓存击穿的概念
在Redis缓存中某条热点数据过期了,然后在这一时间有大量的并发请求到服务器导致缓存中查不到,就都请求到了数据库,数据库压力瞬间增大甚至宕机。
缓存击穿的原因
缓存穿透的概念基本就是它的出现的原因,理论上当在数据库查到数据时会将数据放到缓存,后续请求就可以从缓存中获取到,但是缓存穿透发生的节点就是在数据库查到数据之后和将数据放回缓存之前这一时间段。
缓存击穿的解决办法
- 使用逻辑过期时间
逻辑过期时间类似于Mybatis的逻辑删除,可以对缓存中的数据增加一个expire属性,对应的值就是过期时间。这样当请求过来之后,从缓存中获取到数据判断是否逻辑过期了,如果逻辑过期了就创建一个线程进行缓存重建,注意,这里需要加上互斥锁进行,新开线程是为了不阻塞主线程,而加互斥锁是防止后续的线程也进行缓存重建流程,在缓存重建完成之前主线程都就会直接返回这条过期数据给用户。
**缓存重建:**查询数据库,并重新放入缓存并设置新的逻辑过期时间。
优点:可以保证高可用性。
缺点:在过期重建期间,返回的数据是已经过期的,不能保证数据的完全一致性。
- 互斥锁
当缓存中查询不到该数据时,先获取互斥锁(可以利用redis分布式锁),然后再去查询数据库并将数据重新放入缓存和设置过期时间,最后释放锁。
优点:保