美团面试原题:利用Redis的持久化机制有效避免数据丢失:技巧与最佳实践
Redis持久化机制的重要性
Redis的持久化机制是后端面试中一个极为常见的知识点,值得深入学习和掌握。即便你不是在为面试做准备,这些知识在日常开发中也会频繁用到。
缓存与数据持久化
在使用缓存时,我们常常需要将内存中的数据持久化,以便在机器重启或故障时能够恢复数据,或进行数据同步(例如,Redis集群的主从节点通过RDB文件进行数据同步)。
Redis与Memcached的一个显著区别在于,Redis支持持久化,并提供三种持久化方式:
- 快照(Snapshotting,RDB)
- 只追加文件(Append-Only File,AOF)
- RDB与AOF的混合持久化(新增于Redis 4.0)
官方文档链接:Redis持久化
RDB持久化详解
RDB持久化的定义
Redis通过创建快照来获取内存中数据在某个特定时间点的副本。创建快照后,可以将其备份并复制到其他服务器,进而构建数据相同的服务器副本(适用于Redis的主从结构),这主要用于提高Redis的性能。
快照持久化是Redis默认的持久化方式。以下是redis.conf
配置文件中的默认设置:
save 900 1 # 在900秒内,如果至少有1个key发生变化,Redis将自动触发bgsave命令创建快照。
save 300 10 # 在300秒内,如果至少有10个key发生变化,Redis将自动触发bgsave命令创建快照。
save 60 10000 # 在60秒内,如果至少有10000个key发生变化,Redis将自动触发bgsave命令创建快照。
RDB快照是否会阻塞主线程?
Redis提供两种命令来生成RDB快照文件:
save
: 同步保存操作,会阻塞Redis的主线程;bgsave
: 通过创建子进程来执行,不会阻塞Redis的主线程,这是默认选项。
AOF持久化详解
AOF持久化的定义
相较于快照持久化,AOF(Append-Only File)持久化的实时性更强。Redis在默认情况下并未开启AOF持久化(在Redis 6.0及之后版本中,默认已开启),可以通过appendonly
参数进行配置:
appendonly yes
开启AOF持久化后,每次执行更改Redis中数据的命令,Redis会将该命令写入AOF缓冲区server.aof_buf
,然后再写入AOF文件(此时仍在系统内核缓存区中,尚未同步到磁盘)。
只有在数据同步到磁盘后,才算持久化保存,否则存在数据丢失的风险,例如:如果系统内核缓存区的数据尚未同步,而磁盘故障发生,则这部分数据将丢失。
AOF文件的保存位置与RDB文件相同,通过dir
参数设置,默认文件名为appendonly.aof
。
AOF工作流程
AOF持久化功能的基本流程如下:
- 命令追加(Append):所有写命令会被追加至AOF缓冲区。
- 文件写入(Write):将AOF缓冲区的数据写入AOF文件中。此时调用
write
函数(系统调用),并将数据写入系统内核缓冲区后直接返回(延迟写)。注意,此时并未同步至磁盘。 - 文件同步(Fsync):根据持久化方式(
fsync
策略),AOF缓冲区向硬盘进行同步操作。此步骤需要调用fsync
函数(系统调用),确保磁盘写入操作完成后返回,确保数据持久化。 - 文件重写(Rewrite):随着AOF文件逐渐增大,需要定期对AOF文件进行重写,以达到压缩目的。
- 重启加载(Load):当Redis重启时,可以加载AOF文件进行数据恢复。
AOF持久化方式
在Redis的配置文件中,有三种不同的AOF持久化方式(fsync
策略):
appendfsync always
:主线程调用write
执行写操作后,后台线程立即调用fsync
,这种方式会显著降低Redis性能。appendfsync everysec
:主线程调用write
执行写操作后立即返回,后台线程每秒调用一次fsync
同步AOF文件。appendfsync no
:主线程调用write
执行写操作后立即返回,让操作系统决定同步时机。
为了兼顾数据安全性和写入性能,可以选择appendfsync everysec
选项,使Redis每秒同步一次AOF文件,性能影响较小,且即使发生系统崩溃,用户最多只会丢失一秒内产生的数据。
从Redis 7.0.0开始,Redis引入了Multi Part AOF机制,将原来的单一AOF文件拆分为多个AOF文件。
AOF日志记录机制
Redis的AOF持久化机制在执行命令后记录日志,目的是避免额外的检查开销,且不会阻塞命令执行。虽然这种方式存在风险,比如刚执行完命令后Redis宕机可能导致相应的修改丢失,但从整体性能来看,AOF持久化方式依然得到了广泛应用。
AOF重写机制
当AOF文件过大时,Redis可以在后台自动重写AOF,生成一个新的AOF文件,其状态与原AOF文件一致,但体积更小。重写过程在子进程中执行,同时AOF重写缓冲区会记录所有写命令,确保最终新文件的状态与现有状态一致。
AOF校验机制
AOF校验机制用于在Redis启动时检查AOF文件的完整性,通过使用CRC64算法计算校验和来判断文件是否损坏,确保数据的可靠性。
Redis持久化机制的优化与选择
Redis 4.0及之后版本支持RDB与AOF的混合持久化,结合两者的优点,能够更快速地加载数据并避免数据丢失。
在选择RDB与AOF时,可以根据具体需求决定:
- 如果数据丢失影响不大,使用RDB;
- 不建议单独依赖AOF,定期创建RDB快照以便备份;
- 如果数据安全性要求较高,建议同时开启RDB与AOF或者选择混合持久化。
参考资料
[1] Redis 7.0 Multi Part AOF 的设计和实现: https://zhuanlan.zhihu.com/p/467217082
[2] Redis 的 AOF 方式 #783: https://github.com/Snailclimb/JavaGuide/issues/783
[3] Redis AOF 重写描述不准确 #1439: https://github.com/Snailclimb/JavaGuide/issues/1439
[4] Redis persistence: https://redis.io/docs/manual/persistence/