「RDB 和 AOF 混合持久化」到底混合了什么?答案是:AOF 重写产出的 base 文件是 RDB 格式,之后追加的增量仍是命令文本。这篇用同一份 50 万个 key 的数据集,分别用 RDB、开 preamble 的 AOF、关 preamble 的 AOF 持久化,比较文件格式、大小和重启加载时间。
配置 文件 大小(MB) 文件头 重启加载耗时 AOF + RDB preamble(默认) appendonly.aof.2.base.rdb 39.4 b'REDIS0015\xfa\tredis-ver\x068.10.' 0.26 s (日志: DB loaded from append only file: 0.215 seconds) AOF,无 preamble(纯命令) appendonly.aof.2.base.aof 50.9 b'*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n*3\r' 0.40 s (日志: DB loaded from append only file: 0.374 seconds) 只有 RDB dump.rdb 39.4 b'REDIS0015\xfa\tredis-ver\x068.10.' 0.24 s (日志: DB loaded from disk: 0.222 seconds)
文件头一眼就能分清:preamble 为 yes 时 AOF 的 base 文件以 REDIS0015 开头,是 RDB;为 no 时是 *2\r\n$6\r\nSELECT 开头的 RESP 命令文本。大小:RDB 格式 39.4 MB(与纯 RDB 的 dump.rdb 一样大),命令文本 50.9 MB,大约多 29%。加载耗时(日志里的秒数):0.215 s / 0.374 s / 0.222 s(AOF+preamble / AOF 纯命令 / RDB)。每种配置只做了一次重启测量,毫秒级的差别不要当结论;命令文本更慢这个方向是清楚的(约 74%)。
这里的 value 是随机十六进制字符串,压缩率低,所以 RDB 只比命令文本小两成多;value 像上一个实验(第 54 篇)里那样重复度高时,RDB 会小得多。
39388988 appendonly.aof.2.base.rdb
11188913 appendonly.aof.2.incr.aof
107 appendonly.aof.manifest
incr 文件开头: b'*2\r\n$6\r\nSELECT\r\n$1\r\n0\r\n*3\r\n$3\r\nSET\r\n$5\r\nnew:0\r\n$20\r\nvvvvvvvv'
重启后 DBSIZE = 700000(应为 700000);加载耗时约 0.40 s
Configuration loaded
Successfully created the temporary AOF base file temp-rewriteaof-bg-35706.aof
Fork CoW for AOF rewrite: current 0 MB, peak 0 MB, average 0 MB
Background AOF rewrite terminated with success
Successfully renamed the temporary AOF base file temp-rewriteaof-bg-35706.aof into appendonly.aof.2.base.rdb
Background AOF rewrite finished successfully
Calling fsync() on the AOF file.
Configuration loaded
Reading RDB base file on AOF loading...
RDB is base AOF
Done loading RDB, keys loaded: 500000, keys expired: 0.
DB loaded from base file appendonly.aof.2.base.rdb: 0.202 seconds
DB loaded from incr file appendonly.aof.2.incr.aof: 0.174 seconds
DB loaded from append only file: 0.377 seconds
Opening AOF incr file appendonly.aof.2.incr.aof on server start重写之后再写 20 万个 key,incr 文件是 11.2 MB 的命令文本(开头能看到 SELECT 0 和 SET new:0 …)。重启日志分两段:DB loaded from base file … 0.202 seconds,然后 DB loaded from incr file … 0.174 seconds,合计 0.377 秒,DBSIZE = 700000。增量越大,回放越久——这也是要定期重写的原因。