文章目录
-
- 31 为什么 Redis 不立刻删除已经过期的数据?
-
- 1. Redis 是怎么删除过期 key 的?
- 2. Redis 为什么不立刻删除已经过期的 key?
- 3. Redis 为什么不每个 key 都启动一个定时器,监控过期时间?
- 4. Redis 是如何执行定期删除的?
- 5. 为什么 Redis 在定期删除的时候不一次性把所有的过期 key 都删除掉?
- 6. 当你从 Redis 上查询数据的时候,有可能查询到过期的数据吗?
- 7. 当 Redis 生成 RDB 文件的时候,会怎么处理过期的 key?
- 8. 当 Redis 重写 AOF 文件的时候,会怎么处理过期的 key?
- 9. Redis 定期删除的循环是不是执行得越频繁就越好?
- 10. 如果设计一个本地缓存,你会怎么实现删除过期 key 的功能?
- 11. 你是怎么确定过期时间的?过期时间太长会怎样,太短又会怎样?
- 32 缓存淘汰策略:怎么淘汰缓存命中率才不会下降?
-
- 1. 你知道什么是 LFU,什么是 LRU 吗?可不可以手写一个?
- 2. 什么情况下使用 LFU,什么情况下使用 LRU?
- 3. Redis 支持哪些淘汰策略?你们公司的 Redis 上的淘汰策略使用了哪个?为什么用这个?
- 4. 你使用的本地缓存是如何控制内存使用量的?
- 5. 你业务里面的缓存命中率有多高?还能不能进一步提高?怎么进一步提高?
- 6. 假如说 A 和 B 两个业务共用一个 Redis,那么有办法控制 A 业务的 Redis 内存使用量吗?怎么控制?
- 7. 现在我的业务里面有普通用户和 VIP 用户。现在我希望在缓存内存不足的时候,优先淘汰普通用户的数据,该怎么做?
- 33 缓存模式:缓存模式能不能解决缓存一致性问题?
-
- 1. 什么是 Cache Aside,它能不能解决数据一致性问题?
- 2. 什么是 Read Through,它能不能解决数据一致性问题?
- 3. 什么是 Write Through,它能不能解决数据一致性问题?
- 4. 什么是 Write Back,它有什么缺点,能不能解决一致性问题?
- 5. 什么是 Refresh Ahead,它能不能解决一致性问题?
- 6. 什么是 Singleflight 模式?你用它解决过什么问题?
- 7. 在具体的工作场景中,你是怎么更新数据的?会不会有数据不一致的问题?怎么解决?
- 8. 什么是延迟双删,使用延迟双删能不能解决数据一致性问题?
- 9. 你知道哪些缓存模式,用过哪些模式?
- 34 缓存一致性问题:高并发服务如何保证缓存一致性?
-
- 1. 为什么会有数据不一致的问题?
- 2. 你在使用缓存的时候怎么解决数据不一致的问题?
- 3. 当你的数据不一致的时候,你多久能够发现?
- 4. 如果你使用了本地缓存和 Redis,那么更新数据的时候你怎么更新?
- 5. 使用分布式锁能不能解决数据一致性问题,有什么缺点?
- 6. 你能保证更新数据库和更新缓存同时成功吗?如果不能,你怎么解决?
- 7. 你有什么方法可以解决并发更新导致的数据不一致性问题?
- 35 缓存问题:怎么解决缓存穿透、击穿和雪崩问题?
-
- 1. 什么是缓存穿透、击穿和雪崩?
- 2. 你平时遇到过缓存穿透、击穿和雪崩吗?什么原因引起的?最终是怎么解决的?
- 3. 你还遇到过什么跟缓存有关的事故?最终都是怎么解决的?
- 4. 在你的系统里面,如果 Redis 崩溃了会发生什么?
- 5. 怎么在 Redis 崩溃之后保护好数据库?
- 36 Redis 单线程:为什么 Redis 用单线程而 Memcached 用多线程?
-
- 1. 操作系统中的上下文切换有什么开销?
- 2. Redis 真的是单线程的吗?
- 3. Redis 为什么后面又引入了多线程?
- 4. Redis 后面引入的多线程模型是怎么运作的?相比原本的单线程模型有什么改进?
- 5. 同样是缓存,为什么 Memcached 使用了多线程?
- 6. 什么是 epoll?和 poll、select 比起来,有什么优势?
- 7. 什么是 Reactor 模式?
- 8. 为什么 Redis 的性能那么好?
- 9. 你可以说说 Redis 的 IO 模型吗?
- 10. 为什么 Redis 可以用单线程,但是 Kafka 之类的中间件却不能使用单线程呢?
- 37 分布式锁:如何保证Redis分布式锁的高可用和高性能?
-
- 1. 什么是分布式锁?你用过分布式锁吗?
- 2. 你使用的分布式锁性能如何,可以优化吗?
- 3. 怎么用 Redis 来实现一个分布式锁?
- 4. 怎么确定分布式锁的过期时间?
- 5. 如果分布式锁过期了,但是业务还没有执行完毕,怎么办?
- 6. 加锁的时候得到了超时响应,怎么办?
- 7. 加锁的时候如果锁被人持有了,这时候怎么办?
- 8. 分布式锁为什么要续约?续约失败了怎么办?如果重试一直都失败,怎么办?
- 9. 怎么减少分布式锁竞争?
- 10. 你知道 redlock 是什么吗?
- 38 缓存综合应用:怎么用缓存来提高整个应用的性能?
-
- 1. 你是如何利用缓存来提高系统性能的?
- 2. 当你的缓存崩溃了的时候,你的系统会怎么样?
- 3. 你们公司的 Redis 是如何部署的,性能怎么样?
- 4. 假如说有一个服务 A 要调用服务 B,那么能不能让 A 把 B 的结果缓存下来,这样下次就不用调用了?这种做法有什么优缺点?
-
- 优点:
- 缺点:
- 5. 为什么要做缓存预加载,怎么做预加载?
-
- 原因:
- 做法:
31 为什么 Redis 不立刻删除已经过期的数据?
- Redis 是怎么删除过期 key 的?
- Redis 为什么不立刻删除已经过期的 key?
- Redis 为什么不每个 key 都启动一个定时器,监控过期时间?
- Redis 是如何执行定期删除的?
- 为什么 Redis 在定期删除的时候不一次性把所有的过期 key 都删除掉?
- 当你从 Redis 上查询数据的时候,有可能查询到过期的数据吗?
- 当 Redis 生成 RDB 文件的时候,会怎么处理过期的 key?
- 当 Redis 重写 AOF 文件的时候,会怎么处理过期的 key?
- Redis 定期删除的循环是不是执行得越频繁就越好?
- 如果设计一个本地缓存,你会怎么实现删除过期 key 的功能?
- 你是怎么确定过期时间的?过期时间太长会怎样,太短又会怎样?
1. Redis 是怎么删除过期 key 的?
Redis 使用惰性删除(lazy deletion)和定期删除(periodic deletion)两种策略来删除过期的 key。
- 惰性删除:当客户端尝试访问某个 key 时,Redis 会检查该 key 是否过期,如果已经过期,则在查询时删除它。
- 定期删除:Redis 会周期性地扫描一部分存储的数据,删除其中已经过期的 key。
2. Redis 为什么不立刻删除已经过期的 key?
立刻删除过期的 key 会导致性能开销大,影响 Redis 的响应速度。因为 Redis 是高性能的内存数据库,频繁地执行删除操作可能会造成阻塞,从而影响其他请求的处理。因此,Redis 采用惰性删除和定期删除的策略,以平衡性能与内存的利用。
3. Redis 为什么不每个 key 都启动一个定时器,监控过期时间?
如果每个 key 都启动一个定时器,Redis 的内存和 CPU 开销将会非常大。Redis 可能会有成千上万的 key,创建和维护大量定时器不仅复杂,还会影响 Redis 的性能。因此,Redis 选择了在查询时检测过期(惰性删除)和周期性扫描一部分 key(定期删除)来管理过期数据。
4. Redis 是如何执行定期删除的?
Redis 会在设定的时间间隔内(默认 100ms)随机抽取一部分设置了过期时间的 key 进行检查,并删除已过期的 key。Redis 并不会一次性遍历所有的 key,而是通过抽样的方式控制开销,以保证数据库的稳定性和高性能。
5. 为什么 Redis 在定期删除的时候不一次性把所有的过期 key 都删除掉?
如果一次性删除所有过期的 key 可能会引起系统短暂的停顿,导致响应变慢,尤其在有大量过期 key 的情况下会引发性能瓶颈。因此,Redis 采取分步的方式,避免删除操作对性能的集中影响。
6. 当你从 Redis 上查询数据的时候,有可能查询到过期的数据吗?
可能会。在使用惰性删除策略时,Redis 只有在访问一个 key 时才会检查其是否过期,因此存在查询到已经过期但尚未被删除的 key 的可能性。
7. 当 Redis 生成 RDB 文件的时候,会怎么处理过期的 key?
在生成 RDB 文件时,Redis 会检查并跳过已过期的 key。只有未过期的 key 才会被写入到 RDB 文件中,以保证备份文件的有效性和数据的准确性。
8. 当 Redis 重写 AOF 文件的时候,会怎么处理过期的 key?
在 AOF 重写过程中,Redis 会跳过已过期的 key,确保重写后的 AOF 文件只包含有效数据。因此,在 AOF 文件重写完成后,可以减少文件体积,提升持久化效率。
9. Redis 定期删除的循环是不是执行得越频繁就越好?
不一定。定期删除的循环过于频繁会占用过多的 CPU 资源,影响正常的请求处理。因此需要合理地设置频率,找到删除操作与性能之间的平衡点。一般情况下,Redis 的默认设置已经比较合理。
10. 如果设计一个本地缓存,你会怎么实现删除过期 key 的功能?
可以考虑与 Redis 类似的策略,结合惰性删除和定期删除:
- 惰性删除:在访问缓存数据时检查是否过期,如果过期则删除。
- 定期删除:设定一个定时任务,周期性地随机检查一部分缓存数据并删除过期的 key。
11. 你是怎么确定过期时间的?过期时间太长会怎样,太短又会怎样?
过期时间的确定取决于业务需求:
- 如果过期时间太长,缓存会占用更多的内存,但可以减少缓存失效导致的数据库访问压力。
- 如果过期时间太短,虽然节省了内存,但可能会频繁访问后端数据库,增加负载。因此,需要权衡存储资源和访问效率来合理设定。
32 缓存淘汰策略:怎么淘汰缓存命中率才不会下降?
- 你知道什么是 LFU,什么是 LRU 吗?可不可以手写一个?
- 什么情况下使用 LFU,什么情况下使用 LRU?
- Redis 支持哪些淘汰策略?你们公司的 Redis 上的淘汰策略使用了哪个?为什么用这个?
- 你使用的本地缓存是如何控制内存使用量的?
- 你业务里面的缓存命中率有多高?还能不能进一步提高?怎么进一步提高?
- 假如说 A 和 B 两个业务共用一个 Redis,那么有办法控制 A 业务的 Redis 内存使用量吗?怎么控制?
- 现在我的业务里面有普通用户和 VIP 用户。现在我希望在缓存内存不足的时候,优先淘汰普通用户的数据,该怎么做?
1. 你知道什么是 LFU,什么是 LRU 吗?可不可以手写一个?
- LFU(Least Frequently Used):最少使用策略。缓存会优先淘汰访问频率最低的数据,即被访问次数最少的元素。
- LRU(Least Recently Used):最近最少使用策略。优先淘汰一段时间内没有被访问的数据,即最近最少使用的元素。
示例代码展示一个简单的 LRU 缓存,可以使用 Python 的 OrderedDict
实现:
python复制代码from collections import OrderedDict
class LRUCache:
def __init__(self, capacity: int):
self.cache = OrderedDict()
self.capacity = capacity
def get(self, key: int) -> int:
if key not in self.cache:
return -1
self.cache.move_to_end(key) # 将访问的 key 移到末尾
return self.cache[key]
def put(self, key: int, value: int) -> None:
if key in self.cache:
self.cache.move_to_end(key)
self.cache[key] = value
if len(self.cache) > self.capacity:
self.cache.popitem(last=False) # 删除最旧的
# 使用示例
cache = LRUCache(2)
cache.put(1, 1)
cache.put(2, 2)
print