文章

面试题学习笔记 | Redis 数据存储与管理

Redis 的数据存储是基于内存的,这种特性带来了高效的性能,但也使数据存储和管理面临两个主要问题

  1. 数据持久化问题:由于数据存储在内存中,如果服务器宕机,内存数据就会丢失,这与缓存雪崩问题有一定的相似之处。因此,我们需要合适的持久化策略来保障 Redis 数据的持久性

  2. 数据删除策略:相较于磁盘,内存资源十分有限,我们无法无限制地存储数据而不进行删除,否则会占用过多的内存空间,影响 Redis 的正常运行

Redis 的持久化机制

Redis 主要提供了三种持久化方式:AOF(Append Only File)日志、RDB(Redis Database)快照以及混合持久化(Hybrid Persistence)。AOF 和 RDB 各有优缺点,因此在实际应用中,混合持久化往往是更优的选择

RDB(Redis Database)快照

RDB 持久化机制通过创建快照来记录某个时间点的内存数据,并将其保存到磁盘,默认的快照文件名为 dump.rdb。这不仅有助于数据备份和恢复,还可以用于主从复制

redis.conf 配置文件中,可以设置当一定时间内有指定数量的 key 发生变化时,触发 RDB 持久化

RDB 的优点

  1. 数据加载速度快:RDB 文件是经过压缩的二进制文件,体积较小,因此在服务器启动时可以快速恢复数据

  2. 资源占用低:RDB 持久化通过子进程进行,主线程不会被阻塞,保证了 Redis 的高性能

RDB 的缺点

  1. 由于 RDB 是间隔存储快照的,如果 Redis 在快照保存间隔期间宕机,则会丢失该间隔内的数据

  2. RDB 生成快照时,会占用一定的 CPU 资源和磁盘 I/O,可能会对 Redis 运行产生短暂影响

RDB 持久化的两种方式

  • save:由主线程直接生成 RDB 文件,在生成期间,Redis 无法执行其他命令,需要阻塞直到 RDB 生成完毕

  • bgsave:使用 fork 生成子进程,由子进程负责 RDB 生成,不会阻塞主线程,因此 Redis 默认采用 bgsave 进行 RDB 持久化

bgsave 的执行流程

  1. 检查当前是否有其他 AOF / RDB 持久化子进程正在运行,若有则返回错误

  2. 触发 rdbSaveBackground 持久化操作

  3. fork 生成子进程,由子进程执行 RDB 生成,主线程可继续处理请求

  4. RDB 生成完毕后,替换原有的 RDB 文件,子进程退出

需要注意的是,bgsave 也会造成短暂阻塞,因为 fork 操作需要复制进程元数据,同时 fork 机制依赖于 写时复制(Copy-On-Write),类似于 Java 的 CopyOnWriteArrayList,即主进程和子进程共享相同的内存数据,仅在修改数据时才进行内存复制

AOF(Append Only File)日志

AOF 通过将 Redis 的每个写入操作以追加的方式记录到 AOF 文件中,从而实现持久化。当 Redis 重启时,可以通过重放 AOF 文件中的指令恢复数据

AOF 的优点

  1. 可靠性更高,相比 RDB,它记录了所有写入操作,数据丢失的可能性更低

  2. AOF 文件是以文本格式存储的,可读性较强,便于恢复和排查问题

AOF 的缺点

  1. AOF 文件体积通常比 RDB 文件大,占用更多磁盘空间

  2. AOF 存储的是操作指令,数据恢复需要逐条执行命令,因此恢复速度较慢

AOF 的同步策略

AOF 并不会立即将数据写入磁盘,而是先写入缓冲区,再根据不同的同步策略落盘

  • always:每次写入后立刻调用 fsync,保证数据安全,但严重影响性能

  • everysec(默认):每秒执行一次 fsync,在数据安全性和性能之间做平衡,最多丢失 1 秒数据

  • no:完全由操作系统决定何时将数据同步到磁盘,性能最高但数据安全性最低

AOF 重写机制

由于 AOF 采用追加写入,随着时间推移,文件体积会不断增大。因此,Redis 提供了 AOF 重写机制 来优化 AOF 文件的大小

AOF 重写流程

  1. 通过 bgrewriteaof 命令创建子进程,执行 AOF 重写

  2. 子进程根据当前 Redis 数据,生成一个新的 AOF 文件,仅保留最新数据的写入命令

  3. 主线程仍然接受新的写入操作,并将其追加到 aof_rewrite_buf 缓冲区

  4. AOF 重写完成后,主线程将缓冲区中的增量数据追加到新的 AOF 文件

  5. 替换旧的 AOF 文件

AOF 重写可以手动触发(bgrewriteaof),也可以在 redis.conf 配置自动触发,如当 AOF 文件增大一定比例时触发重写(默认 64MB)

混合持久化

Redis 4.0 引入了 混合持久化 方式,它结合了 RDB 和 AOF 的优点,提高数据恢复速度的同时减少数据丢失概率

在 AOF 重写时,Redis 先生成一份 RDB 快照,并将其写入 AOF 文件的前半部分,然后在此基础上追加增量 AOF 操作。当 Redis 重新启动时,它会优先加载 RDB 部分,并执行后续 AOF 命令,从而实现快速恢复

Redis 过期数据的删除策略

Redis 提供了两种主要的过期数据删除策略

定期删除

Redis 设有定期任务,每 100 毫秒扫描部分设置了过期时间的键,并删除已过期的数据。由于一次性遍历所有键的开销过大,Redis 采取抽样方式,逐步删除一部分过期键,同时限制单次扫描时间(默认不超过 25 毫秒)

惰性删除

当某个键被访问时,Redis 检查其是否过期,若已过期则删除。惰性删除不会影响 Redis 性能,但若某些键长期未被访问,可能会导致内存泄漏

Redis 淘汰策略

当 Redis 内存达到 maxmemory 限制时,Redis 会启动数据淘汰策略,主动删除部分数据释放空间,主要有以下几种

  • noeviction:不删除键,仅拒绝写入新数据(默认策略)

  • volatile-lru:从设置了过期时间的键中删除最久未使用的键

  • volatile-ttl:优先删除存活时间最短的键

  • allkeys-lru:从所有键中删除最久未使用的键

  • allkeys-lfu:从所有键中删除使用频率最低的键

Redis 默认使用 惰性删除 + 定期删除,淘汰策略仅在内存耗尽时作为兜底手段

总结

  • Redis 持久化机制

    • RDB(快照):定期保存数据到磁盘,恢复速度快,但可能丢失最近的数据

    • AOF(日志):记录所有写操作,数据更安全,但文件大,恢复速度慢

    • 混合持久化:结合 RDB 和 AOF 的优点,提高恢复速度并减少数据丢失

  • 数据删除策略

    • 定期删除:每隔一段时间扫描并删除部分过期键,减少内存占用

    • 惰性删除:在访问键时检查是否过期,节省 CPU 但可能导致内存泄漏

  • 数据淘汰策略(当内存达到上限时触发):

    • noeviction(默认):不删除键,直接拒绝新写入

    • LRU(最近最少使用) / LFU(最少使用频率):淘汰最久未使用或使用最少的键

    • TTL 优先:优先删除存活时间最短的键

💡 实践建议

  • 生产环境推荐 AOF + RDB 混合持久化,确保数据安全和恢复效率

  • 选择合适的 数据删除策略,避免过期数据占用内存

  • 配置 淘汰策略,防止 Redis 内存耗尽导致服务不可用

License:  CC BY 4.0