为什么需要持久化
Redis 是内存数据库,进程崩溃或服务器断电后,内存数据全部消失。持久化机制将内存数据写入磁盘,使 Redis 在重启后能恢复数据,扮演"不那么纯粹"的内存数据库角色。
RDB:快照持久化
RDB(Redis Database Backup)在指定时间点将内存中的全部数据以二进制格式快照到 .rdb 文件。类似数据库的全量备份。
RDB 触发方式
自动触发(save 配置)
# redis.conf
# 900秒内有1次写操作
save 900 1
# 300秒内有10次写操作
save 300 10
# 60秒内有10000次写操作
save 60 10000
# 关闭 RDB
save ""
手动触发
# BGSAVE:异步(推荐)
# fork 子进程后立即返回
BGSAVE
# SAVE:同步(阻塞,慎用)
# 会阻塞 Redis 直到完成
SAVE
# 查看最后一次 RDB 保存时间
LASTSAVE
RDB 配置项
# redis.conf 关键配置
dbfilename dump.rdb # RDB 文件名
dir /var/lib/redis # 存储目录
rdbcompression yes # 使用 LZF 压缩(节省磁盘,略增 CPU)
rdbchecksum yes # 文件末尾加 CRC64 校验和
stop-writes-on-bgsave-error yes # BGSAVE 失败时停止写操作(保护数据一致性)
AOF:追加写日志
AOF(Append Only File)将每条写命令以 RESP 格式追加到 .aof 文件末尾,类似 MySQL 的 binlog。Redis 重启时重放所有命令来恢复数据。
AOF 同步策略(fsync)
AOF 写入分两步:先写到操作系统 page cache,再由 fsync 刷入磁盘。同步策略决定数据安全性和性能的权衡:
| appendfsync 配置 | fsync 时机 | 数据安全 | 性能影响 |
|---|---|---|---|
always | 每条命令执行后立即同步 | 最高(几乎不丢数据) | 最大(每次写磁盘) |
everysec(推荐) | 每秒同步一次 | 高(最多丢1秒数据) | 中(异步后台) |
no | 由操作系统决定(通常30秒) | 低(可能丢失30秒) | 最小 |
AOF 重写:压缩日志文件
AOF 文件会持续增大(如对同一 key 做了 1000 次 SET,文件里有 1000 条记录,但只有最后一条有效)。AOF 重写将内存当前状态转换为最小命令集:
# redis.conf AOF 配置
appendonly yes # 开启 AOF
appendfilename "appendonly.aof"
appendfsync everysec # 推荐:每秒同步
no-appendfsync-on-rewrite no # 重写期间是否暂停同步
# AOF 自动重写触发条件
auto-aof-rewrite-percentage 100 # 文件比上次重写后增长100%时触发
auto-aof-rewrite-min-size 64mb # 最小64MB才触发重写
# 手动触发 AOF 重写
BGREWRITEAOF
混合持久化(推荐生产配置)
Redis 4.0 引入混合模式:AOF 重写时,文件头部写入 RDB 格式的全量快照,尾部追加增量 AOF 命令。兼顾了 RDB 的快速恢复和 AOF 的数据安全。
# 开启混合持久化
aof-use-rdb-preamble yes # Redis 7.x 默认已开启
数据恢复流程
持久化性能影响分析
| 方案 | 写性能影响 | 恢复速度 | 数据安全 | 文件大小 |
|---|---|---|---|---|
| 不持久化 | 无影响 | N/A(重启丢数据) | 最低 | N/A |
| RDB only | 低(fork 瞬间暂停微秒~毫秒) | 最快 | 低(可能丢几分钟) | 最小(压缩二进制) |
| AOF everysec | 中(后台 fsync) | 慢(重放命令) | 高(最多丢1秒) | 大(文本格式) |
| AOF always | 高(每次写磁盘) | 慢 | 最高 | 大 |
| 混合模式 | 中 | 快 | 高 | 中 |
fork 导致主进程阻塞:BGSAVE 和 BGREWRITEAOF 在 fork 时会短暂阻塞主进程(Linux 需要复制页表)。内存越大阻塞越长——100GB 内存的 Redis 实例 fork 可能阻塞数秒!应定期监控 INFO persistence 中的 rdb_last_bgsave_time_sec,并使用内存大页(Transparent Huge Pages)前需评估其对 fork 的影响。
Redis 7.0 Multi-Part AOF
Redis 7.0 对 AOF 进行了重大架构升级——将单一的 appendonly.aof 文件拆分为多个部分,存放在一个子目录中:
Redis 7.0+ 的 AOF 改进:Multi-Part AOF 解决了旧版本 AOF 重写的两个主要问题:① 重写期间需要将新增命令同时写到旧 AOF 和重写缓冲区,导致内存双倍占用;② 重写完成时需要原子替换文件,存在短暂风险。新架构完全规避了这些问题。升级到 Redis 7.0+ 后建议开启此功能。
TLS 加密传输
生产环境中 Redis 应启用 TLS(Transport Layer Security)防止数据在网络传输中被窃听,尤其是跨机房或使用云服务时:
# 1. 生成自签名证书(测试用,生产使用 CA 签发)
openssl req -x509 -newkey rsa:4096 -keyout redis.key -out redis.crt \
-days 365 -nodes -subj "/CN=redis-server"
# 2. redis.conf TLS 配置
tls-port 6380 # TLS 端口(保留 6379 作为内部不加密端口)
tls-cert-file /etc/redis/redis.crt
tls-key-file /etc/redis/redis.key
tls-ca-cert-file /etc/redis/ca.crt
tls-auth-clients yes # 要求客户端也提供证书(双向 TLS)
tls-protocols "TLSv1.2 TLSv1.3"
tls-ciphers DEFAULT:!RC4:!3DES
# 3. Python 客户端使用 TLS
import redis, ssl
# 创建 SSL Context
ssl_context = ssl.create_default_context(cafile='/etc/redis/ca.crt')
ssl_context.load_cert_chain(
certfile='/etc/redis/client.crt',
keyfile='/etc/redis/client.key'
)
# 连接到 TLS 端口
r = redis.Redis(
host='redis.example.com',
port=6380,
ssl=True,
ssl_context=ssl_context,
decode_responses=True
)
print(r.ping()) # True
生产环境推荐配置
# /etc/redis/redis.conf 生产推荐
# 混合持久化
appendonly yes
appendfsync everysec
aof-use-rdb-preamble yes
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
# RDB(作为额外备份)
save 3600 1 # 1小时有1次写则保存
save 300 100 # 5分钟有100次写则保存
rdbcompression yes
rdbchecksum yes
# 数据目录(建议独立磁盘)
dir /data/redis
dbfilename dump.rdb
# 检查持久化状态
redis-cli INFO persistence | grep -E "rdb_|aof_"
# 关键指标说明:
# rdb_last_bgsave_status: ok ← 最后一次 BGSAVE 是否成功
# rdb_last_bgsave_time_sec: 2 ← 上次 BGSAVE 耗时(秒)
# aof_current_size: 52428800 ← AOF 当前大小(字节)
# aof_rewrite_in_progress: 0 ← 是否正在重写
Redis 持久化是"内存性能"与"数据安全"的权衡,核心选择原则:
纯缓存场景:关闭持久化(save "",appendonly no),重启从数据库重建缓存。获得最高性能,接受重启数据丢失。
数据不可丢失:开启混合持久化(appendonly yes + aof-use-rdb-preamble yes),使用 everysec 同步策略。最多丢失 1 秒数据,恢复速度快。
金融级安全:AOF always + 主从复制,双重保障。性能代价是每条命令必须等待磁盘写入确认。
运维关键:监控 fork 耗时(rdb_last_bgsave_time_sec);避免在高峰期手动触发 BGSAVE;Redis 7.0+ 的 Multi-Part AOF 显著降低了重写内存压力,应及时升级。
TLS:跨公网或多租户环境必须启用 TLS,防止数据被窃听;内网环境可以使用 IPSec/私有网络替代。