redis持久化机制及其日志
RDB机制
RDB是某一时刻全量数据快照,把内存数据一次性写入 .rdb 二进制文件,保存到磁盘
触发方式
-
自动触发
Redis通过配置文件中save参数定义了 RDB 的自动保存条件。以下是默认配置的示例:save 900 1 # 如果900秒内至少有1个键发生变化,则保存快照 save 300 10 # 如果300秒内至少有10个键发生变化,则保存快照 save 60 10000 # 如果60秒内至少有10000个键发生变化,则保存快照 -
手动触发
save: 同步执行 , 阻塞主线程, 生产禁用bgsave: 后台异步, fork子进程进行, 占用部分内存/cpu资源
优缺点分析
- 优点:
- 文件小 , 恢复速度快,适合定期备份,容灾恢复
- 缺点:
- 丢失最后一次快照后的数据 , 不适合实时性要求高场景
AOF机制
AOF 记录每一条写命令(类似 MySQL binlog),以文本形式追加到 appendonly.aof。
但是如果Redis刚刚执行完一个写命令,还没来得及写AOF文件就宕机了,那么这个命令和相应的数据就会丢失了。但是他也比RDB要更加靠谱一些。
配置命令
appendonly yes # 开启 AOF
appendfilename appendonly.aof # AOF持久化文件名
appendfsync everysec # 刷盘策略
写回策略
- Always,同步写回:每个写命令执行完,立马同步地将日志写回磁盘;
- Everysec,每秒写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,每隔一秒把缓冲区中的内容写入磁盘;
- No,操作系统控制的写回:每个写命令执行完,只是先把日志写到AOF文件的内存缓冲区,由操作系统决定何时将缓冲区内容写回磁盘。
效率:NO>EverySec>Always
可靠性:Always > EverySec > NO
AOF重写
随着命令写入AOF文件,越来越大,因此提供了AOF重写压缩文件
配置:
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
AOF 比上次重写后增大 100% 且大于 64MB 时自动重写。
优缺点分析
- 优点:
- 数据安全性,实时性高 , Everysec策略最多丢失1秒
- 日志追加为顺序IO,性能高
- 缺点:
- 恢复速度慢
- 高写入环境IO压力大
- 文件大
RDB和AOF对比
| 特性 | RDB | AOF |
|---|---|---|
| 数据可靠性 | 可能会丢失最后一次快照之后的数据 | 保证最后一次写操作之前的数据不会丢失 |
| 性能 | 读写性能较高,适合做数据恢复 | 写性能较高,适合做数据存档 |
| 存储空间占用 | 快照文件较小,占用空间较少 | AOF文件较大,占用空间较多 |
| 恢复时间 | 从快照文件中恢复数据较快 | 从AOF文件中恢复数据较慢 |
混合使用
AOF 文件前半部分是 RDB 格式全量数据,后半部分是 AOF 格式增量命令
配置
aof-use-rdb-preamble yes
结合AOF和RDB的优点, 恢复速度快 , 数据实时性高(丢失少)
持久化是否可以确保数据不丢失?
不行
即使是在always策略下,也不能保证100%不丢失数据:
-
磁盘和系统故障:如果在写入操作和同步到磁盘之间发生硬件故障或系统崩溃,可能会丢失最近的写操作。
-
操作系统缓冲区:即使Redis请求立即将数据同步到磁盘,操作系统的I/O缓冲区可能会导致实际写入磁盘的操作延迟发生。如果在写入缓冲区之后,没写磁盘前,机器挂了,那么数据就丢了。
操作系统缓冲区,通常指的是操作系统用于管理数据输入输出(I/O)的一种内存区域。当程序进行文件写入操作时,数据通常首先被写入到这个缓冲区,而不是直接写入到硬盘。
-
磁盘写入延迟:磁盘的写入并非实时完成,特别是在涉及到机械硬盘时,写入延迟主要由磁盘旋转速度(RPM)和寻道时间决定。如果在这这个延迟过程中,机器挂了,那么数据也就丢了。
持久化配置最佳实践
#=========================================
# RDB 快照配置(用于冷备 + 快速恢复)
#=========================================
save 3600 1
save 300 100
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /var/lib/redis
#=========================================
# AOF 配置(保证数据安全,核心推荐)
#=========================================
appendonly yes # 开启 AOF
appendfilename "appendonly.aof"
# 刷盘策略:生产标准方案
appendfsync everysec
# 重写时不 fsync,降低磁盘压力,避免阻塞
no-appendfsync-on-rewrite yes
# AOF 重写触发策略
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
#=========================================
# 混合持久化(Redis 4.0+ 强烈推荐)
#=========================================
aof-use-rdb-preamble yes # 开启 RDB+AOF 混合模式
#=========================================
# 高级优化(减少 fork 阻塞 & 提升稳定性)
#=========================================
repl-diskless-sync yes
repl-diskless-sync-delay 5
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
replica-lazy-flush yes
# 降低 fork 内存拷贝压力
oom-score-adj -1000
maxmemory 16G # 根据实际机器内存调整
混合持久化日志解析
在redis开启混合持久化后 , 执行以下命令作为测试数据
> SADD test:a 111
1
> SADD test:a 23213
1
> SADD test:b 1231231
1
> SADD test:c kkdaod
1
在/var/lib/redis/appendonlydir 中执行
[root@VM-0-4-opencloudos appendonlydir]# ls
appendonly.aof.1.base.rdb appendonly.aof.1.incr.aof appendonly.aof.manifest
[root@VM-0-4-opencloudos appendonlydir]# cat appendonly.aof.manifest
file appendonly.aof.1.base.rdb seq 1 type b
file appendonly.aof.1.incr.aof seq 1 type i
[root@VM-0-4-opencloudos appendonlydir]# cat appendonly.aof.1.incr.aof
*2
$6
SELECT
$1
1
*3
$4
sadd
$6
test:a
$5
23213
*3
$4
sadd
$6
test:b
$7
1231231
*3
$4
sadd
$6
test:c
$6
kkdaod
[root@VM-0-4-opencloudos appendonlydir]# redis-check-rdb appendonly.aof.1.base.rdb
[offset 0] Checking RDB file appendonly.aof.1.base.rdb
[offset 26] AUX FIELD redis-ver = '7.2.7'
[offset 40] AUX FIELD redis-bits = '64'
[offset 52] AUX FIELD ctime = '1775113532'
[offset 67] AUX FIELD used-mem = '866752'
[offset 79] AUX FIELD aof-base = '1'
[offset 88] Checksum OK
[offset 88] \o/ RDB looks OK! \o/
[info] 0 keys read
[info] 0 expires
[info] 0 already expired
其中三个文件appendonly.aof.1.base.rdb/appendonly.aof.1.incr.aof/appendonly.aof.manifest
base : 基础快照RDB的二进制快照文件
incr: AOF的新增命令
manifest: 清单文件,记录有哪些文件
appendonly.aof.1.incr.aof 的从内容则可以看出是我们执行的命令
*3
$4
sadd
$6
test:c
$6
kkdaod
==> SADD test:c kkdaod
*2
$6
SELECT
$1
1
==> select 1 #使用数据库1
因为RDB的快照为二进制文件,使用redis命令redis-check-rdb查看
其结果通过ai解释
# 执行命令:使用Redis自带的redis-check-rdb工具,检查指定的RDB文件是否完整、合法
[root@VM-0-4-opencloudos appendonlydir]# redis-check-rdb appendonly.aof.1.base.rdb
# 日志:从文件偏移量0开始,检查目标RDB文件(该文件是Redis AOF持久化的基础RDB文件)
[offset 0] Checking RDB file appendonly.aof.1.base.rdb
# 日志:偏移量26处,读取到辅助字段:Redis服务版本为7.2.7
[offset 26] AUX FIELD redis-ver = '7.2.7'
# 日志:偏移量40处,读取到辅助字段:Redis运行在64位系统
[offset 40] AUX FIELD redis-bits = '64'
# 日志:偏移量52处,读取到辅助字段:RDB文件创建时间戳(1775113532)
[offset 52] AUX FIELD ctime = '1775113532'
# 日志:偏移量67处,读取到辅助字段:RDB文件生成时Redis占用内存大小(866752字节)
[offset 67] AUX FIELD used-mem = '866752'
# 日志:偏移量79处,读取到辅助字段:标记该文件是AOF持久化的基础RDB文件(1=是)
[offset 79] AUX FIELD aof-base = '1'
# 日志:偏移量88处,文件校验和验证通过(文件无损坏、无篡改)
[offset 88] Checksum OK
# 日志:偏移量88处,RDB文件检查完成,文件状态健康
[offset 88] \o/ RDB looks OK! \o/
# 日志:统计信息:本次检查读取到0个键值对
[info] 0 keys read
# 日志:统计信息:0个键设置了过期时间
[info] 0 expires
# 日志:统计信息:0个键已经过期
[info] 0 already expired
可以看出我们刚才执行的命令只是被添加到AOF追加文件中 , 接下来我们执行BGREWRITEAOF命令来重写AOF文件
[root@VM-0-4-opencloudos appendonlydir]# ls
appendonly.aof.2.base.rdb appendonly.aof.2.incr.aof appendonly.aof.manifest
[root@VM-0-4-opencloudos appendonlydir]# cat appendonly.aof.manifest
file appendonly.aof.2.base.rdb seq 2 type b
file appendonly.aof.2.incr.aof seq 2 type i
[root@VM-0-4-opencloudos appendonlydir]# cat appendonly.aof.2.incr.aof
[root@VM-0-4-opencloudos appendonlydir]# redis-check-rdb appendonly.aof.2.base.rdb
[offset 0] Checking RDB file appendonly.aof.2.base.rdb
[offset 26] AUX FIELD redis-ver = '7.2.7'
[offset 40] AUX FIELD redis-bits = '64'
[offset 52] AUX FIELD ctime = '1775117162'
[offset 67] AUX FIELD used-mem = '1162592'
[offset 79] AUX FIELD aof-base = '1'
[offset 81] Selecting DB ID 1
[offset 157] Checksum OK
[offset 157] \o/ RDB looks OK! \o/
[info] 3 keys read
[info] 0 expires
[info] 0 already expired
重新执行一遍命令,可以看出看到AOF文件为空 , 而RDB二进制文件添加了3个键值对 , 这就是一次持久化中,redis持久化日志的变化

浙公网安备 33010602011771号