Redis 面试的一些问题

内存策略

1. 内存淘汰有哪些,分别适用于哪些场景

Redis 过期策略是:定期删除+惰性删除

  • 消极方法(passive way),在主键被访问时如果发现它已经失效,那么就删除它。
  • 主动方法(active way),定期从设置了失效时间的主键中选择一部分失效的主键删除。

2. 有哪些删除失效key的方法

  • noeviction - 当内存使用达到阈值的时候,所有引起申请内存的命令会报错。这是 Redis 默认的策略。
  • allkeys-lru - 在主键空间中,优先移除最近未使用的 key。
  • allkeys-random - 在主键空间中,随机移除某个 key。
  • volatile-lru - 在设置了过期时间的键空间中,优先移除最近未使用的 key。
  • volatile-random - 在设置了过期时间的键空间中,随机移除某个 key。
  • volatile-ttl - 在设置了过期时间的键空间中,具有更早过期时间的 key 优先移除。

3. 如何选择淘汰策略

  • 如果**数据呈现幂等分布(存在热点数据,部分数据访问频率高,部分数据访问频率低),则使用 allkeys-lru**。
  • 如果**数据呈现平等分布(数据访问频率大致相同),则使用 allkeys-random**。
  • 如果希望**使用不同的 TTL 值向 Redis 提示哪些 key 更适合被淘汰,请使用 volatile-ttl**。
  • volatile-lruvolatile-random 适合既应用于缓存和又应用于持久化存储的场景,然而我们也可以通过使用两个 Redis 实例来达到相同的效果。
  • 将 key 设置过期时间实际上会消耗更多的内存,因此建议使用 allkeys-lru 策略从而更有效率的使用内存

4. 设计一个LRU算法

可以继承 LinkedHashMap,并覆写 removeEldestEntry 方法来实现一个最简单的 LRUCache

内存淘汰要点

  • 最大缓存 - Redis 允许通过 maxmemory 参数来设置内存最大值。
  • 失效时间 - 作为一种定期清理无效数据的重要机制,在 Redis 提供的诸多命令中,EXPIREEXPIREATPEXPIREPEXPIREAT 以及 SETEXPSETEX 均可以用来设置一条键值对的失效时间。而一条键值对一旦被关联了失效时间就会在到期后自动删除(或者说变得无法访问更为准确)。
  • 淘汰策略 - 随着不断的向 Redis 中保存数据,当内存剩余空间无法满足添加的数据时,Redis 内就会施行数据淘汰策略,清除一部分内容然后保证新的数据可以保存到内存中。内存淘汰机制是为了更好的使用内存,用一定得 miss 来换取内存的利用率,保证 Redis 缓存中保存的都是热点数据。
  • 非精准的 LRU - 实际上 Redis 实现的 LRU 并不是可靠的 LRU,也就是名义上我们使用 LRU 算法淘汰键,但是实际上被淘汰的键并不一定是真正的最久没用的。

持久化

不同持久化方式的特性和原理是什么?

Redis 会周期性生成 RDB 文件。
生成 RDB 流程:Redis fork 一个子进程,负责生成 RDB;生成 RDB 采用 Copy On Write 模式,此时,如果收到写请求,会在原副本上操作,不影响工作。
RDB 只能恢复生成快照时刻的数据,之后的数据无法恢复。生成 RDB 的资源开销高昂。RDB 适合做冷备。

AOF 会将写命令不断追加到 AOF 文本日志末尾。

AOF 丢数据比 RDB 少,但文件会比 RDB 文件大很多。

一般,AOF 设置 appendfsync 同步频率为 everysec 即可。

建议同时使用 RDB 和 AOF。用 AOF 来保证数据不丢失,作为数据恢复的第一选择; 用 RDB 来做不同程度的冷备,在 AOF 文件都丢失或损坏不可用的时候,还可以使用 RDB 来进行快速的数据恢复。

Redis 管道

Redis 是一种基于 C/S 模型以及请求/响应协议的 TCP 服务。Redis 支持管道技术。管道技术允许请求以异步方式发送,即旧请求的应答还未返回的情况下,允许发送新请求。这种方式可以大大提高传输效率。使用管道发送命令时,Redis Server 会将部分请求放到缓存队列中(占用内存),执行完毕后一次性发送结果。如果需要发送大量的命令,会占用大量的内存,因此应该按照合理数量分批次的处理。