【Redis源码】详细的RDB和AOF持久化过程(五)

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【Redis源码】详细的RDB和AOF持久化过程(五)

(一)分析RDB和AOF的优劣势:

优劣势官方介绍:https://redis.io/topics/persistence
 持久化详细介绍:http://oldblog.antirez.com/post/redis-persistence-demystified.html

1.RDB:

RDB的优点:

1)RDB是redis数据非常紧凑的单文件时间点表示。RDB文件非常适合备份。例如,您可能希望在最近的24小时内每小时存档一次

RDB文件,并在30天之内每天保存一次RDB快照。这使您可以在灾难情况下轻松还原数据集的不同版本。

2) RDB对于灾难恢复非常有用,它是一个紧凑文件,可以传输到远程中心或Amazon S上。

3)RDB最大限度地提高了redis的性能,因为redis父进程为了持久化而需要做的唯一个就是开辟一个子进程,其余所有工作都要做。父进程将永远不会执行磁盘I/O;

4)与AOF相比,RDB允许大型数据集更快地重启。

RDB的缺点:

1)如果需要最大程度地减少数据丢失的可能性(比如说redis停止工作,例如说断电之后)。则RDB不好。您可以在生成RDB的位置配置不同的保存点(例如,在至少5分钟之后,对数据集进行100次写入,但是您可以有多个保存点)。但是,通常会每个5分钟或更长的时间创建一次RDB的快照,因此,如果Redis出于任何原因在没有正确关闭的情况下停止工作,则应该准备丢失最新的数据分钟。

2)RDB需要经常使用fork()函数才能使用子进程将其持久化在磁盘上。如果数据集很大,fork()可能很耗时,并且如果数据集很大且

CPU性能不佳,则可能导致Redis停止为服务器服务几毫秒甚至一秒种。AOF也是用fork(),但是您可以调整要重写日志的频率,而无需权衡持久性。

2.AOF

AOF的优点:

1)使用AOF Redis更加持久:您可以使用不同的fsync策略:完全没有fsync,每秒fsync,每个查询fsync。使用默认策略fsync时,每秒的写入性能仍然很好(fsync是使用后台线程执行的,并且在没有进行fsync的情况下,主线程将尽力执行写入操作。)但是您只能损失一秒钟的写入时间。

2)AOF日志是仅追加的日志,因此,如果断电,则不会出现寻道或损坏问题。即使由于某种原因(磁盘已满或其他原因)以半写命令结束日志,redis-check-aof工具也可以轻松修复它。

3)Redis太大时,Redis可以在后台自动重写AOF。重写是完全安全的,因为Redis继续追加到旧文件时,会生成一个全新的文件,其中包含创建当前数据集所需的最少操作集,一旦准备好第二个文件,Redis会切换这两个文件并开始追加到新的那一个。

4)AOF以易于理解和解析的格式包含所有操作的日志。您甚至可以轻松导出AOF文件。例如,即使您使用FLUSHALL命令刷新了所有错误文件,如果在此期间未执行任何日志重写操作,您仍然可以保存数据集,只是停止服务器,删除最新命令并重新启动Redis。

AOF的缺点:

1)对于同一数据集,AOF文件通常大于等效的RDB文件。

2)根据确切的fsync策略,AOF可能比RDB慢。通常,在将fsync设置为每秒的情况下,性能仍然很高,并且在禁用fsync的情况下,即使在高负载下,它也应与RDB一样快。即使在巨大的写负载的情况下,RDB仍然能够提供有关最大延迟的更多保证。

3)过去,我们在特定命令中遇到过罕见的错误(例如,其中有一个涉及阻止命令,例如BPROPLPUSH),导致生成的AOF在重载时无法重现完全相同的数据集。这些错误很少见,我们在测试套件中进行了测试,自动创建了随机的复杂数据集,然后重新加载它们以检查一切是否正常。但是,RDB持久性几乎是不可能的。为了更清楚地说明这一点:Redis AOF通过增量更新现有状态来工作,就像MySQL或MongoDB一样,而RDB快照一次又一次地创建所有内容,从概念上讲更健壮。但是- 1)应该注意的是,每次Redis重写AOF时,都会从数据集中包含的实际数据开始重新创建AOF,与始终附加AOF文件(或重写为读取旧AOF而不是读取内存中的数据)相比,提高了对错误的抵抗力。2)我们从未收到过有关真实环境中检测到的AOF损坏的用户报告。

(二)redis.conf配置

dbfilename dump.rdb              #rdb持久化文件名称

#“save 900 1”表示如果900秒内至少1个key发生变化(新增、修改和删除),则重写rdb文件;
save 900 1      

#“save 300 10”表示如果300秒内至少10个key发生变化(新增、修改和删除),则重写rdb文件;
save 300 10

#“save 60 10000”表示如果60秒内至少10000个key发生变化(新增、修改和删除),则重写rdb文件;
save 60 10000

appendonly yes                   #是否开启aof。no关闭,yes开启
appendfilename "appendonly.aof"  #aof文件名称


appendfsync everysec   #设置项可以设置  everysec、always、no 三种        
#everysec fsync每秒写入。always fsync每次每次将新命令附加AOF文件,no 从不fsync,只需将数据交给操作系统即可。
#no是最快的一种,但是不安全。通常,Linux使用此配置每30秒刷新一次数据。但这取决于内核的精准调整。

aof-use-rdb-preamble yes #混合模式

(三)RDB持久化过程

触发rdb同步写入快照文件的形式有三种:

1)自动触发:save,bgsave命令

2)根据redis.conf,serverCron触发

3)主从同步时触发;

lldb跟踪效果

生成临时文件

临时文件替换过程

临时文件rename后变为dump.rdb文件,则文件的md5会发生改变。

rdb.c 源码:

/* SAVE 命令*/
voidsaveCommand(client *c) {
   if (server.rdb_child_pid != -1) {  //判断是否RDB有子进程
       addReplyError(c,"Background save already in progress");
       return;
   }
   if (rdbSave(server.rdb_filename,NULL) == C_OK) {
       addReply(c,shared.ok);
   } else {
       addReply(c,shared.err);
   }
}

/* BGSAVE 命令*/
voidbgsaveCommand(client *c) {
   int schedule = 0;
   ...省略
   
   if (server.rdb_child_pid != -1) { 。//判断是否有RDB子进程
       addReplyError(c,"Background save already in progress");
   } elseif (server.aof_child_pid != -1) { //判断是否有AOF子进程
       ...省略
   } elseif (rdbSaveBackground(server.rdb_filename,NULL) == C_OK) { //异步创建快照
       addReplyStatus(c,"Background saving started");
   } else {
       addReply(c,shared.err);
   }
}

intrdbSave(char *filename, rdbSaveInfo *rsi) {
   char tmpfile[256];
   char cwd[MAXPATHLEN]; /* Current working dir path for error messages. */
   FILE *fp;
   rio rdb;
   int error = 0;
    //生成临时文件
    snprintf(tmpfile,256,"temp-%d.rdb", (int) getpid());
   fp = fopen(tmpfile,"w");
   ...省略
   
   if (rdbSaveRio(&rdb,&error,RDB_SAVE_NONE,rsi) == C_ERR) { //写入数据
       errno = error;
       goto werr;
   }

   /* Make sure data will not remain on the OS's output buffers */
   if (fflush(fp) == EOF) goto werr;
   if (fsync(fileno(fp)) == -1) goto werr;
   if (fclose(fp) == EOF) goto werr;

   //临时文件替换成redis.conf的dbfilename的配置快照名称
   if (rename(tmpfile,filename) == -1) {
     ...省略
   }
   return C_OK;

werr:
   serverLog(LL_WARNING,"Write error saving DB on disk: %s", strerror(errno));
   fclose(fp);
   unlink(tmpfile);
   return C_ERR;
}

intrdbSaveBackground(char *filename, rdbSaveInfo *rsi) {
   pid_t childpid;
   longlong start;

   if (server.aof_child_pid != -1 || server.rdb_child_pid != -1) return C_ERR;

   server.dirty_before_bgsave = server.dirty;
   server.lastbgsave_try = time(NULL);
   openChildInfoPipe();

   start = ustime();
   if ((childpid = fork()) == 0) { //fork子进程
       int retval;

       /* Child */
       closeListeningSockets(0);
       redisSetProcTitle("redis-rdb-bgsave");
       retval = rdbSave(filename,rsi);  //调用rdbSave生成快照
       ...省略
       exitFromChild((retval == C_OK) ? 0 : 1);
   } else {
       /* 父进程 */
       server.stat_fork_time = ustime()-start;
       server.stat_fork_rate = (double) zmalloc_used_memory() * 1000000 / server.stat_fork_time / (1024*1024*1024); /* GB per second. */
       latencyAddSampleIfNeeded("fork",server.stat_fork_time/1000);
       ...省略
       return C_OK;
   }
   return C_OK; /* unreached */
}

(四)AOF持久化过程

AOF写入形式有有两种:

1)bgrewriteaof命令写入

2)serverCron中调中写入

aof与rdb不同的是,aof是完全异步写入。fork了子进程去完成写入过程;

aof文件

总结:

rdb持久化:

1)rdb文件比较适合用于数据恢复,但是它不安全。容易造成数据丢失;

2)rdb文件数据大的情况下写入时会有一些影响;

3) 如果

aof持久化:

1)aof在数据安全性上会比rdb高,如果突发意外情况,只会丢失1秒数据;

2)aof生成的文件比较大,如果使用incr增加到100,则会有100条记录;

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
1天前
|
监控 NoSQL 测试技术
【赵渝强老师】Redis的AOF数据持久化
Redis 是内存数据库,提供数据持久化功能,支持 RDB 和 AOF 两种方式。AOF 以日志形式记录每个写操作,支持定期重写以压缩文件。默认情况下,AOF 功能关闭,需在 `redis.conf` 中启用。通过 `info` 命令可监控 AOF 状态。AOF 重写功能可有效控制文件大小,避免性能下降。
|
1天前
|
存储 监控 NoSQL
【赵渝强老师】Redis的RDB数据持久化
Redis 是内存数据库,提供数据持久化功能以防止服务器进程退出导致数据丢失。Redis 支持 RDB 和 AOF 两种持久化方式,其中 RDB 是默认的持久化方式。RDB 通过在指定时间间隔内将内存中的数据快照写入磁盘,确保数据的安全性和恢复能力。RDB 持久化机制包括创建子进程、将数据写入临时文件并替换旧文件等步骤。优点包括适合大规模数据恢复和低数据完整性要求的场景,但也有数据完整性和一致性较低及备份时占用内存的缺点。
|
1月前
|
存储 缓存 NoSQL
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
35 2
大数据-45 Redis 持久化概念 RDB AOF机制 持久化原因和对比
|
1月前
|
存储 缓存 NoSQL
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
大数据-46 Redis 持久化 RDB AOF 配置参数 混合模式 具体原理 触发方式 优点与缺点
56 1
|
6月前
|
NoSQL 关系型数据库 MySQL
Redis持久化机制 RDB 和 AOF 的选择
Redis持久化机制 RDB 和 AOF 的选择
97 0
|
6月前
|
存储 缓存 NoSQL
Redis之持久化(RDB和AOF)
Redis之持久化(RDB和AOF)
140 0
|
2月前
|
存储 缓存 NoSQL
Redis中的rdb和aof
本文深入探讨了Redis的持久化机制,包括RDB和AOF两种方式。详细解释了RDB的工作原理、优势和劣势,以及AOF的实现原理、配置选项、文件重写机制和三种数据同步方式,还介绍了AOF文件修复工具redis-check-aof的使用,并通过实例展示了如何开启和配置AOF持久化方式。
Redis中的rdb和aof
|
2月前
|
存储 NoSQL Redis
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
Redis持久化、RDB和AOF方案、Redis主从集群、哨兵、分片集群、散列插槽、自动手动故障转移
SpringCloud基础7——Redis分布式缓存,RDB,AOF持久化+主从+哨兵+分片集群
|
3月前
|
缓存 NoSQL Redis
redis数据持久化之RDB和AOF
redis数据持久化之RDB和AOF
|
5月前
|
存储 NoSQL Redis
《面试官之你说我听》:简明的图解Redis RDB持久化、AOF持久化
《面试官之你说我听》:简明的图解Redis RDB持久化、AOF持久化
下一篇
无影云桌面