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

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 【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
相关文章
|
27天前
|
存储 NoSQL Redis
保障数据安全,提升性能:探秘Redis AOF持久化机制在在线购物网站的应用
保障数据安全,提升性能:探秘Redis AOF持久化机制在在线购物网站的应用
|
1月前
|
存储 缓存 NoSQL
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(一)
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)
40 0
|
1月前
|
存储 NoSQL 算法
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(二)
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)
49 0
|
2天前
|
存储 NoSQL 算法
给我说说Redis持久化机制RDB吧
给我说说Redis持久化机制RDB吧
8 0
|
11天前
|
存储 NoSQL Java
Redis奔溃了快看看有没开启持久化
Reis作为一个内存数据库,整个数据库状态都存储在内存里,如果在运行过程中发生崩溃,那整个数据库状态可就完全不见了,相当于整个服务器被初始化。Redis在这方面肯定有所作为,我们来看看它做了什么功夫~
127 0
Redis奔溃了快看看有没开启持久化
|
12天前
|
人工智能 前端开发 Java
Java语言开发的AI智慧导诊系统源码springboot+redis 3D互联网智导诊系统源码
智慧导诊解决盲目就诊问题,减轻分诊工作压力。降低挂错号比例,优化就诊流程,有效提高线上线下医疗机构接诊效率。可通过人体画像选择症状部位,了解对应病症信息和推荐就医科室。
157 10
|
21天前
|
存储 NoSQL 算法
redis数据持久化
redis数据持久化
|
1月前
|
存储 机器学习/深度学习 NoSQL
作者推荐 |【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(链表)(二)
作者推荐 |【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(链表)
23 0
|
1月前
|
存储 缓存 NoSQL
作者推荐 |【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(链表)(一)
作者推荐 |【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(链表)
29 0
|
1月前
|
缓存 NoSQL Shell
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
【Redis深度专题】「核心技术提升」探究Redis服务启动的过程机制的技术原理和流程分析的指南(持久化功能分析)
163 0