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

简介: 【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条记录;

相关文章
|
6月前
|
NoSQL 安全 关系型数据库
Redis:持久化的两种方式
Redis持久化机制主要包括RDB和AOF两种方式。RDB通过生成数据快照进行持久化,支持手动或自动触发,具有加载速度快、文件紧凑等特点,但无法实时保存数据。AOF则记录每个操作命令,保障数据更安全,支持多种写入策略,并可通过重写机制优化文件大小。两者各有优劣,常结合使用以兼顾性能与数据安全。
|
6月前
|
存储 缓存 NoSQL
Redis持久化深度解析:数据安全与性能的平衡艺术
Redis持久化解决内存数据易失问题,提供RDB快照与AOF日志两种机制。RDB恢复快、性能高,但可能丢数据;AOF安全性高,最多丢1秒数据,支持多种写回策略,适合不同场景。Redis 4.0+支持混合持久化,兼顾速度与安全。根据业务需求选择合适方案,实现数据可靠与性能平衡。(238字)
|
9月前
|
存储 监控 NoSQL
流量洪峰应对术:Redis持久化策略与内存压测避坑指南
本文深入解析Redis持久化策略与内存优化技巧,涵盖RDB快照机制、AOF重写原理及混合持久化实践。通过实测数据揭示bgsave内存翻倍风险、Hash结构内存节省方案,并提供高并发场景下的主从复制冲突解决策略。结合压测工具链构建与故障恢复演练,总结出生产环境最佳实践清单。
342 9
|
存储 NoSQL 安全
Redis的两种持久化方式---RDB、AOF
通过本文的介绍,我们详细讲解了Redis的两种主要持久化方式:RDB和AOF。每种方式都有其独特的优缺点和适用场景。在实际应用中,可以根据具体需求选择合适的持久化方式,或者同时启用RDB和AOF,以达到最佳效果。希望本文能帮助您更好地理解和应用Redis的持久化机制,构建高效、可靠的数据存储解决方案。
1176 79
|
9月前
|
机器学习/深度学习 数据采集 人机交互
springboot+redis互联网医院智能导诊系统源码,基于医疗大模型、知识图谱、人机交互方式实现
智能导诊系统基于医疗大模型、知识图谱与人机交互技术,解决患者“知症不知病”“挂错号”等问题。通过多模态交互(语音、文字、图片等)收集病情信息,结合医学知识图谱和深度推理,实现精准的科室推荐和分级诊疗引导。系统支持基于规则模板和数据模型两种开发原理:前者依赖人工设定症状-科室规则,后者通过机器学习或深度学习分析问诊数据。其特点包括快速病情收集、智能病症关联推理、最佳就医推荐、分级导流以及与院内平台联动,提升患者就诊效率和服务体验。技术架构采用 SpringBoot+Redis+MyBatis Plus+MySQL+RocketMQ,确保高效稳定运行。
662 0
|
12月前
|
NoSQL Redis
Redis的数据持久化策略有哪些 ?
Redis 提供了两种方式,实现数据的持久化到硬盘。 1. RDB 持久化(全量),是指在指定的时间间隔内将内存中的数据集快照写入磁盘。 2. AOF持久化(增量),以日志的形式记录服务器所处理的每一个写、删除操作 RDB和AOF一起使用, 在Redis4.0版本支持混合持久化方式 ( 设置 aof-use-rdb-preamble yes )
|
NoSQL Redis
03- Redis的数据持久化策略有哪些 ?
Redis的数据持久化包括两种策略:RDB(全量快照)和AOF(增量日志)。RDB在指定时间间隔将内存数据集保存到磁盘,而AOF记录所有写操作形成日志。从Redis 4.0开始,支持RDB和AOF的混合持久化,通过设置`aof-use-rdb-preamble yes`。
206 1
|
NoSQL 安全 Redis
redis持久化策略
Redis 提供了两种主要的持久化策略:RDB(Redis DataBase)和AOF(Append Only File)。RDB通过定期快照将内存数据保存为二进制文件,适用于快速备份与恢复,但可能因定期保存导致数据丢失。AOF则通过记录所有写操作来确保数据安全性,适合频繁写入场景,但文件较大且恢复速度较慢。两者结合使用可增强数据持久性和恢复能力,同时Redis还支持复制功能提升数据可用性和容错性。
288 5
|
canal 缓存 NoSQL
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;先删除缓存还是先修改数据库,双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
Redis常见面试题(一):Redis使用场景,缓存、分布式锁;缓存穿透、缓存击穿、缓存雪崩;双写一致,Canal,Redis持久化,数据过期策略,数据淘汰策略
|
存储 缓存 JSON
Redis-持久化-淘汰机制-IO策略
Redis-持久化-淘汰机制-IO策略