Redis 缓存持久化是指将内存中的数据保存到磁盘中,以防服务器故障导致数据丢失。Redis 提供了两种主要的持久化方式:RDB 快照和 AOF 日志。
RDB 快照持久化
RDB 持久化方式通过创建数据在某一时刻的快照来实现持久化。
触发机制
- 自动触发:可以通过配置文件
redis.conf
来设置自动进行 RDB 快照的条件。 - 手动触发:使用
SAVE
或BGSAVE
命令。
配置文件示例 (redis.conf
)
save 900 1 # 在900秒内,如果超过1个键被改动,进行自动保存操作
save 300 10 # 在300秒内,如果超过10个键被改动,进行自动保存操作
save 60 10000 # 在60秒内,如果超过10000个键被改动,进行自动保存操作
源码概览
Redis 的 RDB 持久化是在 rdb.c
文件中实现的。以下是一个简化的伪代码,用于理解 RDB 的持久化流程:
void rdbSave(char *filename) {
// 创建一个文件用于写入 RDB 数据
FILE *fp = fopen(filename, "w");
// 保存数据库的元数据
saveType(fp);
// 遍历所有数据库
for (int i = 0; i < server.dbnum; i++) {
// 遍历数据库中的所有键值对
dictIterator *di = dictGetIterator(server.db[i].dict);
dictEntry *de;
while((de = dictNext(di)) != NULL) {
// 保存键值对
saveKeyValuePair(fp, de);
}
dictReleaseIterator(di);
}
// 写入 EOF 标记
saveEOF(fp);
fclose(fp);
}
AOF 持久化
AOF 持久化通过记录写操作命令到 AOF 文件来实现持久化。
触发机制
- 自动触发:每次写命令执行时,如果开启 AOF,命令会被追加到 AOF 文件。
- 手动触发:使用
BGREWRITEAOF
命令,可以重写 AOF 文件以压缩其体积。
配置文件示例 (redis.conf
)
appendonly yes # 开启 AOF 功能
appendfsync everysec # 设置同步的频率,每秒同步一次
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
源码概览
AOF 持久化主要在 aof.c
文件中实现。以下是一个简化的伪代码,用于理解 AOF 的记录流程:
void feedAppendOnlyFile(struct redisCommand *cmd, int dbid, robj **argv, int argc) {
// 开始构建 AOF 缓冲
sds aof_buf = sdsempty();
// 将命令和参数添加到 AOF 缓冲
for (int i = 0; i < argc; i++) {
aof_buf = sdscatprintf(aof_buf, "%s ", argv[i]->ptr);
}
// 追加到 AOF 文件
int fd = open(server.aof_filename, O_WRONLY|O_APPEND);
if (fd == -1) return;
if (write(fd, aof_buf, sdslen(aof_buf)) == -1) {
// 处理错误
}
close(fd);
}
持久化策略选择
- 数据安全性优先:如果数据安全性是首要考虑,则应优先使用 AOF 持久化并设置
appendfsync
为always
。 - 性能优先:如果性能是关键因素,则可以选择 RDB 或将 AOF 的
appendfsync
设置为everysec
或no
。 - 混合模式:在极高的数据安全性和恢复需求的场景下,可以同时使用 RDB 和 AOF。
注意事项
- 数据完整性:在 Redis 崩溃重启后,RDB 可能会丢失在最后一次快照之后的所有数据,而 AOF 通常可以恢复更多的数据。
- 性能考量:RDB 在保存大数据集时可能会导致长时间的延迟,而 AOF 命令的写入可能会降低写操作的吞吐量。
- 重写与压缩:随着时间的推移,AOF 文件可能会变得非常大,所以定期重写 AOF 文件是一个好的实践。
- 监控与管理:监控 RDB 和 AOF 的大小,以及持久化操作的性能对于 Redis 的稳定运行至关重要。
在实现具体的解决方案时,需要根据实际业务的特点和需求,合理选择和配置持久化策略,以及定期进行持久化文件的维护和优化。