Tags

  • 技术

31 为什么 Redis 不立刻删除已经过期的数据?

  1. Redis 是怎么删除过期 key 的?
    懒惰删除:访问时检查; 定期删除: 定期选择一部分key, 查看是否过期再决定是否删除, 平衡性能.
    
  2. Redis 为什么不立刻删除已经过期的 key?
    如果有大量的key, 完全删除会消耗不少cpu时间, 为了平衡性能, 只能是懒惰删除+定期删除.
    
  3. Redis 为什么不每个 key 都启动一个定时器,监控过期时间?
    开销太大,修改定时还要重置
    
  4. Redis 是如何执行定期删除的?
    根据后台任务执行频率, 定期选择一批key 检测, 过期则删除.
    
  5. 为什么 Redis 在定期删除的时候不一次性把所有的过期 key 都删除掉?
    量太大, 平衡性能只能一部分一部分检测删除
    
  6. 当你从 Redis 上查询数据的时候,有可能查询到过期的数据吗?
    主从模式下, v3.2之前有个bug, 从库查询能查到.
    
  7. 当 Redis 生成 RDB 文件的时候,会怎么处理过期的 key?
    主库不读不写, 从库全读全写
    
  8. 当 Redis 重写 AOF 文件的时候,会怎么处理过期的 key?
    追加一条删除命令
    
  9. Redis 定期删除的循环是不是执行得越频繁就越好?
    也不是, 后台删除任务执行就会损耗cpu时间,要平衡性能.
    
  10. 如果设计一个本地缓存,你会怎么实现删除过期 key 的功能?
    懒惰删除+定期删除
    
  11. 你是怎么确定过期时间的?过期时间太长会怎样,太短又会怎样?
    根据业务评估. 过期时间太长占内存, 缓存利用率太低, 太短命中率不够.
    

32 缓存淘汰策略:怎么淘汰缓存命中率才不会下降?

  1. 你知道什么是 LFU,什么是 LRU 吗?可不可以手写一个?
    lfu: 频率数量, 最不经常使用; lru: 时间, 最近最少使用
    lfu: 最小堆+hashmap 构成; lru: 双端链表+hashmap 构成
    

    lru+lfu 实现

  2. 什么情况下使用 LFU,什么情况下使用 LRU?
    通常lru , 对于时间局部性应用良好.lfu 可用作优先级变种基础使用.
    
  3. Redis 支持哪些淘汰策略?你们公司的 Redis 上的淘汰策略使用了哪个?为什么用这个?
    noeviction:不淘汰任何键,写操作会失败。
    volatile-lru:淘汰设置了过期时间的键中最近最少使用的键。
    allkeys-lru:淘汰所有键中最近最少使用的键。
    volatile-lfu:淘汰设置了过期时间的键中使用频率最低的键。
    allkeys-lfu:淘汰所有键中使用频率最低的键。
    volatile-ttl:淘汰设置了过期时间的键中过期时间最短的键。
    random:随机淘汰键。
    
  4. 你使用的本地缓存是如何控制内存使用量的?
    如果用redis 可以设置 maxmemory 控制最大内存使用量
    
  5. 你业务里面的缓存命中率有多高?还能不能进一步提高?怎么进一步提高?
    增大内存,缓存更多数据;
    优化缓存策略;
    
  6. 假如说 A 和 B 两个业务共用一个 Redis,那么有办法控制 A 业务的 Redis 内存使用量 吗?怎么控制?
    记录总使用量
    
  7. 现在我的业务里面有普通用户和 VIP 用户。现在我希望在缓存内存不足的时候,优先淘汰普通用户的数据,该怎么做?
    vip 用户的缓存优先级设置为更高. 淘汰的时候先淘汰优先级低的数据. [key 标签分组、缓存时间]
    

33 缓存模式:缓存模式能不能解决缓存一致性问题?

  1. 什么是 Cache Aside,它能不能解决数据一致性问题?
    写:应用层写数据库, 写缓存; 读:缓存未读到, 应用层读数据库、写缓存.
    写过程会引发数据一致性问题.
    
  2. 什么是 Read Through,它能不能解决数据一致性问题?
    写同cache aside,  读: 缓存未读到, 缓存层读数据库、写缓存.
    写过程同cache aside
    
  3. 什么是 Write Through,它能不能解决数据一致性问题?
    读同cache aside; 写: 交由缓存层写数据库
    写过程虽然交由缓存层来写入, 但是模式还是同cache aside 的写类似, 所以还是有数据一致性问题.
    
  4. 什么是 Write Back,它有什么缺点,能不能解决一致性问题?
    写:只是写缓存, key 过期同步数据到数据库; 读: 缓存没读到, 读数据库, 回写缓存使用setnx 失败, 失败则读取最新的缓存数据并返回.
    如果能排出缓存的高可用问题, 极大的能缓解数据一致性问题.
    
  5. 什么是 Refresh Ahead,它能不能解决一致性问题?
    监听binlog,  写数据库写缓存; 读: 同 write back
    
  6. 什么是 Singleflight 模式?你用它解决过什么问题?
    如果缓存失效, 同一时间多个线程对同一个key的访问, 只允许一个线程真正到数据库取数据. 减少数据压力.
    
  7. 在具体的工作场景中,你是怎么更新数据的?会不会有数据不一致的问题?怎么解决?
    用过删除模式: 读缓存未找到 到再次写入缓存过程中, 有写数据库删缓存发生,就会有数据不一致的情况. 可以考虑延时双删, 减缓数据不一致性的情况.
    
  8. 什么是延迟双删,使用延迟双删能不能解决数据一致性问题?
    类似删除模式, 就是在删除模式的写入过程中, 再多删除一次, 减缓数据不一致的情况.
    
  9. 你知道哪些缓存模式,用过哪些模式?
    [综合1~8]
    

35 缓存问题:怎么解决缓存穿透、击穿和雪崩问题?

  1. 什么是缓存穿透、击穿和雪崩?
    穿透:数据库没数据
    击穿:同时大量key访问数据库
    雪崩:同时大量key过期
    
  2. 你平时遇到过缓存穿透、击穿和雪崩吗?什么原因引起的?最终是怎么解决的?
    缓存穿透: 布隆过滤器+redis缓存
    击穿: singleflight 限制同一时刻只能有一个线程去访问数据库
    雪崩: 分散过期时间
    
  3. 在你的系统里面,如果 Redis 崩溃了会发生什么?
    缓存写入失败, 数据丢失, 强依赖服务不可用
    
  4. 怎么在 Redis 崩溃之后保护好数据库?
    限流、降级、做好监控报警
    

36 Redis 单线程:为什么 Redis 用单线程而 Memcached 用多线程?

  1. 操作系统中的上下文切换有什么开销?
    线程或进程状态的保存和恢复, 系统调用开销、锁竞争和同步
    
  2. Redis 真的是单线程的吗?
    命令的执行是单线程的
    
  3. Redis 为什么后面又引入了多线程?
    io 可以是多线程的, 充分利用多核cpu的能力
    
  4. Redis 后面的引入的多线程模型是怎么运作的?相比原本的单线程模型有什么改进?
    主线程负责处理事件、创建连接、执行命令; io 多线程用来处理读写数据.
    
  5. 同样是缓存,为什么 Memcached 使用了多线程?
    设计问题
    
  6. 什么是 epoll?和 poll、select 比起来,有什么优势?
    select:
    文件描述符集合数量有限制
    每次设置都要重置fd_set
    内核需要遍历所有文件描述符来检查是否有事件就绪
    poll:
    没有文件描述符固定限制
    每次依旧要重置fd数组
    内核依旧需要遍历检查
    epoll:
    通过将fd和感兴趣的事件注册到epoll 实例上, 通过事件表和回调, 内核只会返回有事件的文件描述符.
    
  7. 什么是 Reactor 模式?
    简单讲就是一个分发器+多个处理器
    
  8. 为什么 Redis 的性能那么好?/你可以说说 Redis 的 IO 模型吗?
    利用了epoll 处理io 事件+ reactor 模式分发处理具体的io读写
    

    9.为什么 Redis 可以用单线程,但是 Kafka 之类的中间件确不能使用单线程呢?

    kafka 需要高吞吐量, 需要处理磁盘io
    

37 分布式锁:如何保证Redis分布式锁的高可用和高性能?

  1. 什么是分布式锁?你用过分布式锁吗?
    支持排他性操作; 使用过基于redis 的分布式锁
    
  2. 怎么用 Redis 来实现一个分布式锁?
    setnx + ttl
    
  3. 怎么确定分布式锁的过期时间?
    业务正常执行完成事件的99线
    
  4. 如果分布式锁过期了,但是业务还没有执行完毕,怎么办?
    可以提供续约机制
    
  5. 加锁的时候得到了超时响应,怎么办?
    重试或者等待
    
  6. 加锁的时候如果锁被人持有了,这时候怎么办?
    中断或者等待
    
  7. 分布式锁为什么要续约?续约失败了怎么办?如果重试一直都失败,怎么办?
    业务可能在过期之前还没完成.
    续约失败重试、释放或者重新获取、告警然后业务补偿.
    
  8. 怎么减少分布式锁竞争?
    优化锁的粒度
    减少锁的持有时间
    合理设置锁的过期时间
    
  9. 你知道 redlock 是什么吗?
    多数原则, 向所有redis 实例获取锁, 多数1/2以上获取成功则成功; 释放锁时要向所有实例发送释放请求.
    

38 缓存综合应用:怎么用缓存来提高整个应用的性能?

  1. 你是如何利用缓存来提高系统性能的?
    发起微服务调用,应用客户端缓存;
    具体服务:使用一致性哈希+本地+redis缓存
    调整第三方中间件的缓存设置, 比如 mysql innodb 的 buffer bool.
    
  2. 当你的缓存崩溃了的时候,你的系统会怎么样?
    缓存不可用直接告警, 读取数据不存在, 系统会直接查询数据库.
    
  3. 你们公司的 Redis 是如何部署的,性能怎么样?
    使用的云服务
    
  4. 假如说有一个服务 A 要调用服务 B,那么能不能让 A 把 B 的结果缓存下来,这样下次就不用调用了?这种做法有什么优缺点?
    可以缓存,但是要确保数据一致性就需要当B 的结果发生变化时, 能够删除掉旧的缓存.
    
  5. 为什么要做缓存预加载,怎么做预加载?
    提高热点数据的访问性能. 应用初始化的时候, 缓存所有的热点数据.