redis是目前最常用的一种nosql数据库,他基于内层运行,性能高效,并且可以实验分布式。在目前的很多场景里面都有使用。
redis的使用场景:
- 缓存
- 分布式锁
- 计数器
- 保存token
- 消息队列
- 延迟队列
其中缓存是一个重点知识:需要了解缓存的穿透击穿和雪崩,还需要了解双写一致和持久化,并且还有数据过期和淘汰策略。
缓存穿透、击穿和雪崩
常见问题:你的项目里面使用了redis缓存,那么关于缓存三兄弟(缓存穿透、击穿和雪崩)你了解哪些?
提问理由:了解项目真实性以及深入发问的切入
- 穿透:查询一个不存在的数据,数据库查询不到就不会写入redis,导致每次请求都会访问数据库。
如果这种不存在的查询非常多,很容易把数据库弄挂。
- 解决方法1:缓存空数据
没有查询到的数据,在redis里面存储null。(能移动程度解决上面的问题,但是如果每次换一个条件,不同的不存在条件查询,数据库还是容易挂)
- 解决方案2:加入布隆过滤器
布隆过滤器就是一个以位为单位的数组,通过三次不同的hash计算得到位置,把位置变成1.查询布隆就是把条件拿去做三次hash,看是不是都是1,如果是表示存在,表示表示不存在。但是可能会出现误判情况,因为数组长度有限。
- 击穿:热点数据过期瞬间,非常夺取请求进入。
- 解决方法1:互斥锁 就是访问时候加锁,如果缓存没有命中,就去数据库查询,这时候其他线程只能被阻塞。(保证了强一致性)
- 解决方法2:逻辑过期(就是不设置过期时间,性能好)
- 雪崩:同一时间大量缓存失效 解决方法:如果是因为缓存时间设置不当,使用随机缓存失效时间,如果是redis宕机,采用主从同步和哨兵模式。
参考:项目中缓存是如何使用的 - 掘金 (juejin.cn)
双写一致性
保证数据库和缓存里面数据一致。
读取比较简单,比如先查询缓存缓存没有查数据库。
怎么进行写操作,比如更新?
延迟双删:其实就是先删除缓存,然后修改数据库,延迟一定时间后,再次删除缓存(因为修改数据库后,需要一定时候对缓存进行更新,延迟一定时间后,数据库主从同步好了,删除缓存,再次查询就一定是之前数据)
但是延迟多久?这个和具体网络环境有关,没有具体的数据。
所以一般我们都是读用共享锁,写有互斥锁完成
数据过期策略
- 惰性:使用时候检测,过期删除(不好:容易内层满)
- 定期:定期随机挑选一些key,把里面过期的删掉