Redis源码简洁剖析13—Redis 持久化原创
Redis 持久化方式
主要参考 Redis 官方文档:Redis Persistence。共有 4 种持久化方式:
- RDB (Redis Database):以指定的时间间隔执行数据在某个时间点的快照。
- AOF (Append Only File):AOF 持久化记录服务器接收到的每个写操作。Redis server 在启动时会重放这些操作,进而重建数据。记录的命令与 Redis 协议的格式相同,并且是以追加的方式记录。当日志变得太大时,Redis 能够在后台 重写 日志。
- No persistence:用户也可以完全禁用持久性,数据只在内存中使用。
- RDB + AOF:可以在同一个实例中结合 AOF 和 RDB。在这种情况下,Redis 重启时会使用 AOF 文件重建原始数据,因为它是最完整的。
RDB
优势
RDB 是 Redis 数据在某个时间点的文件,格式非常紧凑,非常适合作为备份。比如我们可以在最近的 24 小时内,每小时归档一个 RDB 文件,并在 30 天内每天保存一次 RDB 快照。这样我们可以轻松恢复不同版本的数据。
RDB 非常适合灾难恢复,RDB 文件是可以传输的单个紧凑文件。
RDB 提升 Redis 的性能,因为 Redis 父进程为了持久化而做的唯一操作,就是派生一个将完成其余所有操作的子进程。
与 AOF 相比,RDB 在大数据集恢复时更迅速。
劣势
RDB 在 Redis 宕机的情况下,更容易丢失数据。如果我们每 5 分钟创建一次 RDB 快照,如果 Redis 没有正常关闭,那最新几分钟的数据就会丢失。
RDB 需要经常 fork() 出在磁盘上持久化的子进程。在数据很大、CPU 性能不好时,会导致 Redis 在几毫秒甚至一秒内不对外服务。
AOF
以独立日志的方式,记录每次写命令,重启时再重新执行 AOF 文件中的命令,进而回复数据。相对于 RDB 的记录数据,AOF 是记录数据产生的过程。
优势
服务宕机时丢失数据更少,比如仅丢失最后 1s 的数据。
AOF 日志只是附加日志,不会出现寻道问题,也不会在断电时出现损坏。
AOF 日志易于理解和解析,包含所有操作。
劣势
AOF 文件比相同数据集的 RDB 文件大。
取决于具体的 fsync 策略,AOF 可能比 RDB 慢。
Redis < 7.0
在重新期间对数据库的写入,AOF 可能占用大量内存(缓冲在内存中,并在最后写入新的 AOF)。
重写期间,所有写入的命令都会写入磁盘两次。
在 redis.conf 中,可以看到 appendfsync 有 3 个值:
- no: don’t fsync, just let the OS flush the data when it wants. Faster.
- always: fsync after every write to the append only log. Slow, Safest.
- everysec: fsync only one time every second. Compromise.
# The fsync() call tells the Operating System to actually write data on disk
# instead of waiting for more data in the output buffer. Some OS will really flush
# data on disk, some other OS will just try to do it ASAP.
#
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.
# always: fsync after every write to the append only log. Slow, Safest.
# everysec: fsync only one time every second. Compromise.
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# More details please check the following article:
# http://antirez.com/post/redis-persistence-demystified.html
#
# If unsure, use "everysec".
# appendfsync always
appendfsync everysec
# appendfsync no