Redis
Redis的数据持久化策略有哪些?
我看你做的项目中,都用到了redis,你在项目中给你那些场景使用了Redis呢?
如果发生了缓存穿透、击穿、雪崩如何解决呢?
缓存穿透:
- 查询一个不存在的数据,mysql中也查询不到数据也不会直接写入缓存,就会导致每次请求都查数据库
解决方案:
方案一:缓存空数据,查询返回的数据为空,仍把这个空结果进行缓存(消耗内存,可能会发送不一致的问题)
方案二:布隆过滤器:当根据id查询时
缓存击穿:
给某一个key设置了过期时间,当key过期时,恰好在这个时间点对这个key有大量的并发请求过来,这些并发的请求可能会瞬间把DB压垮
解决方案:
- 方案一:互斥锁,强一致,性能差
- 方案二:逻辑过期,高可用,性能优,不能保证数据绝对一致
缓存雪崩:
指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,给DB带来巨大压力
解决方案:
- 给不同的Key的TTL添加随机值
- 利用Redis集群提高服务的可用性(哨兵模式、集群模式)
- 给缓存业务添加降级限流策略(Nginx、SpringCloud Gateway)
- 给业务添加多级缓存(Guava/Caffeine)
会被问到的知识点:
Redis作为缓存,mysql的数据如何与redis进行同步呢?(双写一致性)
- 我当时是把题库论坛的热点数据存到了缓存当中,虽然是热点数据,但是实时要求性并没有那么高,所以我当时采用的是异步的方案同步的数据
- 还有就是抢卷的库存写入到了缓存当中,这个需要实时的进行数据同步,为了保证数据的强一致性,我们当时采用的是Redisson提供的读写锁来保证数据的同步
那你介绍一下你项目当中异步的方案(来介绍一下redisson读写锁的这种方案)
允许延时一致的业务,采用异步通知
使用MQ中间件,更新数据之后,通知缓存删除
利用canal中间件,不需要修改业务代码,伪装为mysql的一个从节点,canal通过读取binlog数据更新缓存
强一致性的,采用Redisson提供的读写锁
共享锁:读锁readLock,加锁之后,其他线程可以共享读操作
排他锁:独占锁writeLock,枷锁之后,阻塞其他线程读写操作
Redis持久化
redis作为缓存,数据的持久化是如何做的?
Redis提供了两种数据持久化的方式:
RDB(Redis Database ):RDB是一个快照文件,他是把Redis内存存储的数据写到磁盘当中,当redis实例宕机恢复数据时,可以从rdb的快照文件中恢复数据。
AOF:AOF是一个追加文件,当redis操作写命令的时候,都会存储到这个文件当中,当redis实例宕机恢复数据的时候会从这个文件中再次执行一遍命令来恢复数据。
这两种方式,哪种恢复的比较快呢?1
RDB是二进制文件,在保存的时候体积也是比较小的,他会封得比较快,但是有可能会丢失数据,而我们通常在项目中使用AOF来恢复数据,虽然AOF恢复的速度慢一些,但是他丢数据的奉孝要小很多,在AOF文件中可以设置刷盘策略
Redis数据删除策略
惰性删除:设置该key过期时间后,我们不去管他,当需要该key时,我们再检查其是否过期,如果过期,我们就删掉他,反之则返回该key
优点:对cpu友好,只会在使用该key时才会进行过期检查,对于很多用不到的key不用浪费时间进行过期检查。
缺点:对内存不友好,如果一个key已经过期,但是一直没有使用,那么该key就会一直存在内存当中,内存永远不会释放
定期删除:每隔一段时间,就会对一些key进行检查,删除里面过期的key(从一定数量的数据库中取出一定数量的随机key进行检查,并删除其中的过期key)
- 优点:可以通过限制删除操作执行的时长和频率来减少删除操作对cpu的影响,另外定期删除,也能有效释放过期key占用的内存。
- 缺点:难以确定删除操作执行的时长和频率
Redis数据淘汰策略
- LRU(Least Recently Used)最近最少使用,用当前的时间减去最后一次使用的时间,值越大则淘汰优先级越高
- LFU(Least Frequently Used)最少频率使用,会统计每个key的访问频率,值越小淘汰优先级越高
会被问到的知识点:
数据库中有1000万数据,而Redis只能缓存20w数据,如何保证Redis中的数据都是热点数据?
使用allkeys-lru(挑选最近最少使用的数据淘汰)淘汰策略,留下来的都是经常访问的热点数据
Redis的内存用完了会发生什么?
主要看数据淘汰策略是什么?如果是默认的配置(noeviction)就会直接报错
面试官你好 今年xx岁