31 为什么 Redis 不立刻删除已经过期的数据?
- Redis 是怎么删除过期 key 的?
懒惰删除:访问时检查; 定期删除: 定期选择一部分key, 查看是否过期再决定是否删除, 平衡性能. - Redis 为什么不立刻删除已经过期的 key?
如果有大量的key, 完全删除会消耗不少cpu时间, 为了平衡性能, 只能是懒惰删除+定期删除. - Redis 为什么不每个 key 都启动一个定时器,监控过期时间?
开销太大,修改定时还要重置 - Redis 是如何执行定期删除的?
根据后台任务执行频率, 定期选择一批key 检测, 过期则删除. - 为什么 Redis 在定期删除的时候不一次性把所有的过期 key 都删除掉?
量太大, 平衡性能只能一部分一部分检测删除 - 当你从 Redis 上查询数据的时候,有可能查询到过期的数据吗?
主从模式下, v3.2之前有个bug, 从库查询能查到. - 当 Redis 生成 RDB 文件的时候,会怎么处理过期的 key?
主库不读不写, 从库全读全写 - 当 Redis 重写 AOF 文件的时候,会怎么处理过期的 key?
追加一条删除命令 - Redis 定期删除的循环是不是执行得越频繁就越好?
也不是, 后台删除任务执行就会损耗cpu时间,要平衡性能. - 如果设计一个本地缓存,你会怎么实现删除过期 key 的功能?
懒惰删除+定期删除 - 你是怎么确定过期时间的?过期时间太长会怎样,太短又会怎样?
根据业务评估. 过期时间太长占内存, 缓存利用率太低, 太短命中率不够.
32 缓存淘汰策略:怎么淘汰缓存命中率才不会下降?
- 你知道什么是 LFU,什么是 LRU 吗?可不可以手写一个?
lfu: 频率数量, 最不经常使用; lru: 时间, 最近最少使用 lfu: 最小堆+hashmap 构成; lru: 双端链表+hashmap 构成 - 什么情况下使用 LFU,什么情况下使用 LRU?
通常lru , 对于时间局部性应用良好.lfu 可用作优先级变种基础使用. - Redis 支持哪些淘汰策略?你们公司的 Redis 上的淘汰策略使用了哪个?为什么用这个?
noeviction:不淘汰任何键,写操作会失败。 volatile-lru:淘汰设置了过期时间的键中最近最少使用的键。 allkeys-lru:淘汰所有键中最近最少使用的键。 volatile-lfu:淘汰设置了过期时间的键中使用频率最低的键。 allkeys-lfu:淘汰所有键中使用频率最低的键。 volatile-ttl:淘汰设置了过期时间的键中过期时间最短的键。 random:随机淘汰键。 - 你使用的本地缓存是如何控制内存使用量的?
如果用redis 可以设置 maxmemory 控制最大内存使用量 - 你业务里面的缓存命中率有多高?还能不能进一步提高?怎么进一步提高?
增大内存,缓存更多数据; 优化缓存策略; - 假如说 A 和 B 两个业务共用一个 Redis,那么有办法控制 A 业务的 Redis 内存使用量
吗?怎么控制?
记录总使用量 - 现在我的业务里面有普通用户和 VIP 用户。现在我希望在缓存内存不足的时候,优先淘汰普通用户的数据,该怎么做?
vip 用户的缓存优先级设置为更高. 淘汰的时候先淘汰优先级低的数据. [key 标签分组、缓存时间]
33 缓存模式:缓存模式能不能解决缓存一致性问题?
- 什么是 Cache Aside,它能不能解决数据一致性问题?
写:应用层写数据库, 写缓存; 读:缓存未读到, 应用层读数据库、写缓存. 写过程会引发数据一致性问题. - 什么是 Read Through,它能不能解决数据一致性问题?
写同cache aside, 读: 缓存未读到, 缓存层读数据库、写缓存. 写过程同cache aside - 什么是 Write Through,它能不能解决数据一致性问题?
读同cache aside; 写: 交由缓存层写数据库 写过程虽然交由缓存层来写入, 但是模式还是同cache aside 的写类似, 所以还是有数据一致性问题. - 什么是 Write Back,它有什么缺点,能不能解决一致性问题?
写:只是写缓存, key 过期同步数据到数据库; 读: 缓存没读到, 读数据库, 回写缓存使用setnx 失败, 失败则读取最新的缓存数据并返回. 如果能排出缓存的高可用问题, 极大的能缓解数据一致性问题. - 什么是 Refresh Ahead,它能不能解决一致性问题?
监听binlog, 写数据库写缓存; 读: 同 write back - 什么是 Singleflight 模式?你用它解决过什么问题?
如果缓存失效, 同一时间多个线程对同一个key的访问, 只允许一个线程真正到数据库取数据. 减少数据压力. - 在具体的工作场景中,你是怎么更新数据的?会不会有数据不一致的问题?怎么解决?
用过删除模式: 读缓存未找到 到再次写入缓存过程中, 有写数据库删缓存发生,就会有数据不一致的情况. 可以考虑延时双删, 减缓数据不一致性的情况. - 什么是延迟双删,使用延迟双删能不能解决数据一致性问题?
类似删除模式, 就是在删除模式的写入过程中, 再多删除一次, 减缓数据不一致的情况. - 你知道哪些缓存模式,用过哪些模式?
[综合1~8]
35 缓存问题:怎么解决缓存穿透、击穿和雪崩问题?
- 什么是缓存穿透、击穿和雪崩?
穿透:数据库没数据 击穿:同时大量key访问数据库 雪崩:同时大量key过期 - 你平时遇到过缓存穿透、击穿和雪崩吗?什么原因引起的?最终是怎么解决的?
缓存穿透: 布隆过滤器+redis缓存 击穿: singleflight 限制同一时刻只能有一个线程去访问数据库 雪崩: 分散过期时间 - 在你的系统里面,如果 Redis 崩溃了会发生什么?
缓存写入失败, 数据丢失, 强依赖服务不可用 - 怎么在 Redis 崩溃之后保护好数据库?
限流、降级、做好监控报警
36 Redis 单线程:为什么 Redis 用单线程而 Memcached 用多线程?
- 操作系统中的上下文切换有什么开销?
线程或进程状态的保存和恢复, 系统调用开销、锁竞争和同步 - Redis 真的是单线程的吗?
命令的执行是单线程的 - Redis 为什么后面又引入了多线程?
io 可以是多线程的, 充分利用多核cpu的能力 - Redis 后面的引入的多线程模型是怎么运作的?相比原本的单线程模型有什么改进?
主线程负责处理事件、创建连接、执行命令; io 多线程用来处理读写数据. - 同样是缓存,为什么 Memcached 使用了多线程?
设计问题 - 什么是 epoll?和 poll、select 比起来,有什么优势?
select: 文件描述符集合数量有限制 每次设置都要重置fd_set 内核需要遍历所有文件描述符来检查是否有事件就绪 poll: 没有文件描述符固定限制 每次依旧要重置fd数组 内核依旧需要遍历检查 epoll: 通过将fd和感兴趣的事件注册到epoll 实例上, 通过事件表和回调, 内核只会返回有事件的文件描述符. - 什么是 Reactor 模式?
简单讲就是一个分发器+多个处理器 - 为什么 Redis 的性能那么好?/你可以说说 Redis 的 IO 模型吗?
利用了epoll 处理io 事件+ reactor 模式分发处理具体的io读写9.为什么 Redis 可以用单线程,但是 Kafka 之类的中间件确不能使用单线程呢?
kafka 需要高吞吐量, 需要处理磁盘io
37 分布式锁:如何保证Redis分布式锁的高可用和高性能?
- 什么是分布式锁?你用过分布式锁吗?
支持排他性操作; 使用过基于redis 的分布式锁 - 怎么用 Redis 来实现一个分布式锁?
setnx + ttl - 怎么确定分布式锁的过期时间?
业务正常执行完成事件的99线 - 如果分布式锁过期了,但是业务还没有执行完毕,怎么办?
可以提供续约机制 - 加锁的时候得到了超时响应,怎么办?
重试或者等待 - 加锁的时候如果锁被人持有了,这时候怎么办?
中断或者等待 - 分布式锁为什么要续约?续约失败了怎么办?如果重试一直都失败,怎么办?
业务可能在过期之前还没完成. 续约失败重试、释放或者重新获取、告警然后业务补偿. - 怎么减少分布式锁竞争?
优化锁的粒度 减少锁的持有时间 合理设置锁的过期时间 - 你知道 redlock 是什么吗?
多数原则, 向所有redis 实例获取锁, 多数1/2以上获取成功则成功; 释放锁时要向所有实例发送释放请求.
38 缓存综合应用:怎么用缓存来提高整个应用的性能?
- 你是如何利用缓存来提高系统性能的?
发起微服务调用,应用客户端缓存; 具体服务:使用一致性哈希+本地+redis缓存 调整第三方中间件的缓存设置, 比如 mysql innodb 的 buffer bool. - 当你的缓存崩溃了的时候,你的系统会怎么样?
缓存不可用直接告警, 读取数据不存在, 系统会直接查询数据库. - 你们公司的 Redis 是如何部署的,性能怎么样?
使用的云服务 - 假如说有一个服务 A 要调用服务 B,那么能不能让 A 把 B 的结果缓存下来,这样下次就不用调用了?这种做法有什么优缺点?
可以缓存,但是要确保数据一致性就需要当B 的结果发生变化时, 能够删除掉旧的缓存. - 为什么要做缓存预加载,怎么做预加载?
提高热点数据的访问性能. 应用初始化的时候, 缓存所有的热点数据.