1.在项目中,那些场景都使用了Redis?
缓存
- 缓存三兄弟(穿透、击穿、雪崩)
- 双写一致
- 持久化
- 数据过期策略
- 数据淘汰策略
分布式锁
- setnx、redisson 消息队列、延迟队列
- 使用的数据类型: string(字符串)、hash(哈希)、list(列表)、set(集合)、zset(有序集合);新版本类型:bitmap、GEO
2.如果发生缓存穿透、击穿、雪崩,该如何解决?
- 穿透
- 请求一个redis和db都不存在的数据,从而给数据库带来压力;
- 解决1:缓存空数据,查询返回数据为空,将空数据进行缓存。(比较消耗内存,数据不一致问题)
- 解决2:布隆过滤器
- bitmap
- 作用:布隆过滤器可以用于检索一个元素是否在一个集合中。
- 击穿
- 热点key在某个时间过期了,这个时间会有大量的并发请求,db宕机;
- 解决1:互斥锁(强一致性、性能差)
- 解决2:设置热点数据永不过期
- 解决3:逻辑过期(高可用、性能好、不能保证数据一致性)
- 雪崩
- 大量的数据过期时间一致,会导致db同时存在大量的访问,数据库可能会宕机;
- 解决1:给不同的key的TTL添加随机值
- 解决2:利用Redis集群
- 解决3:缓存业务进行降级限流策略(nginx、gateway)
- 解决4:多级缓存
redis作为缓存,Mysql的数据如何与redis进行同步呢?(双写一致)
允许延时一致的业务,采用异步通知
- 使用MQ中间中间件,更新数据之后,通知缓存删除1
- 利用canal中间件,不需要修改业务代码,伪装为mysql的一个从节点,canal通过读取binlog数据更新缓存
强一致性的,采用Redisson提供的读写锁
- 共享锁: 读锁readLock,加锁之后,其他线程可以共享读操作
- 排他锁:独占锁writeLock也叫,加锁之后,阻塞其他线程读写操作
redis作为缓存数据的持久化是怎么做的?
- RDB
- AOF
redis的key过期之后,会立即删除吗?
redis的过期删除策略
- 惰性删除:访问key时判断是否过期,过期则删除;
- 定期删除:定期检查一定量的key是否过期(SLOW+FAST模式)
redis的过期策略:惰性删除+定期删除两种策略配合使用
假如缓存过多,内存有限,内存被占满了怎么办?
当Redis中的内存不够用时,此时在向Redis中添加新的key,那么Redis就会按照某一种规则将内存中的数据删除掉,这种数据的删除规则被称之为内存的淘汰策略。
- noeviction: 不淘汰任何key,但是内存满时不允许写入新数据,默认就是这种策略
- volatile-ttl: 对设置了TTL(过期时间)的key,比较key的剩余TTL值,TTL越小越先被淘汰
- allkeys-random:对全体key ,随机进行淘汰 key1是在3s之前访问的, key2是在9s之前访问的,删除的就是key2
- volatile-random:对设置了TTL的key ,随机进行淘汰
- allkeys-lru:对全体key,基于LRU算法进行淘汰
- volatile-lru:对设置了TTL的key,基于LRU算法进行淘汰
- allkeys-lfu:对全体key,基于LFU算法进行淘汰
- volatile-lfu:对设置了TTL的key,基于LFU算法进行淘汰
LRU(Least Recently Used) 最近最少使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。 LFU(Least Frequently Used)最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高。
平时开发过程中使用allkeys-lru淘汰策略比较多(结合使用场景)