REdis AOF文件结构分析
REdis-4.0之前的AOF文件没有文件头,而从REdis-4.0开始AOF文件带有一个文件头,文件头格式和RDB文件头相同。
REdis-4.0版本,如果开启aof-use-rdb-preamble(值为yes,5.0默认为yes,4.0默认为no),则AOF文件内容由三部分组成:
1) 文件头(和RDB文件头格式相同)
2) RDB格式的二进制数据段
3) AOF格式的文本数据段
AOF格式的文本数据段和之前版本的保持相同,如下图所示:
从REdis-4.0开始,AOF有文件头,目的是支持同时加载RDB格式和AOF格式数据。AOF文件头和RDB文件头基本相同,但RDB文件头多了三个字段。
先看AOF和RDB通用部分的文件头内容:
1) 头5字节固定为REDIS
2) 第6~9共四字节为RDB版本号
3) 接下来为redis-ver和它的值,即redis版本
4) 接着redis-bits和它的值,即redis的位数,值为32或64
5) 接着为ctime和它的值,值为当前时间戳
6) 接着为used-mem和它的值
7) 最后是aof-preamble和它的值,值为0或1,1表示RDB有效。
RDB的文件头和AOF的文件基本相同,但RDB文件头在aof-preamble之前多了如下三项:
1) repl-stream-db
2) repl-id
3) repl-offset
如果配置项appendonly值为no,则不会加载AOF文件,而是直接加载RDB文件,因为RDB文件保存了复制信息,所以进程重启可增量复制。而如果置项appendonly值为yes,因为AOF文件头不包含复制信息,所以只能全量复制。
相关代码:
/* Replay the append log file. * On success C_OK is returned. On non fatal * error (the append only file is zero-length) * C_ERR is returned. On * fatal error an error message is logged * and the program exists. */ int loadAppendOnlyFile(char *filename) // aof.c:673 { /* Check if this AOF file has an RDB preamble. In that case we need to * load the RDB file and later continue loading the AOF tail. */ char sig[5]; /* "REDIS" */ if (fread(sig,1,5,fp) != 5 || memcmp(sig,"REDIS",5) != 0) // aof.c:707 { /* No RDB preamble, seek back at 0 offset. */ if (fseek(fp,0,SEEK_SET) == -1) goto readerr; } else { /* RDB preamble. Pass loading the RDB functions. */ if (rdbLoadRio(&rdb,NULL,1) != C_OK) { // aof.c:717 。。。。。。 } } } /* Load an RDB file from the rio stream 'rdb'. * On success C_OK is returned, * otherwise C_ERR is returned and 'errno' is set accordingly. */ int rdbLoadRio(rio *rdb, rdbSaveInfo *rsi, int loading_aof) // rdb.c:1850 { 。。。。。。 } /* Save a few default AUX fields with information about the RDB generated. */ int rdbSaveInfoAuxFields(rio *rdb, int flags, rdbSaveInfo *rsi) // rdb.c:1071 { int redis_bits = (sizeof(void*) == 8) ? 64 : 32; int aof_preamble = (flags & RDB_SAVE_AOF_PREAMBLE) != 0; /* Add a few fields about the state when the RDB was created. */ if (rdbSaveAuxFieldStrStr(rdb,"redis-ver",REDIS_VERSION) == -1) return -1; if (rdbSaveAuxFieldStrInt(rdb,"redis-bits",redis_bits) == -1) return -1; if (rdbSaveAuxFieldStrInt(rdb,"ctime",time(NULL)) == -1) return -1; if (rdbSaveAuxFieldStrInt(rdb,"used-mem",zmalloc_used_memory()) == -1) return -1; /* Handle saving options that generate aux fields. */ // 如果是AOF,传入的rsi为NULL, // 因此不会记录以下三项辅助数据 // 可参见函数rewriteAppendOnlyFile(aof.c:1344)的实现 if (rsi) { // rdb.c:1082 if (rdbSaveAuxFieldStrInt(rdb,"repl-stream-db",rsi->repl_stream_db) == -1) return -1; if (rdbSaveAuxFieldStrStr(rdb,"repl-id",server.replid) == -1) return -1; if (rdbSaveAuxFieldStrInt(rdb,"repl-offset",server.master_repl_offset) == -1) return -1; } if (rdbSaveAuxFieldStrInt(rdb,"aof-preamble",aof_preamble) == -1) return -1; return 1; } /* Produces a dump of the database in RDB format sending it to the specified * Redis I/O channel. On success C_OK is returned, otherwise C_ERR * is returned and part of the output, or all the output, can be * missing because of I/O errors. * * When the function returns C_ERR and if 'error' is not NULL, the * integer pointed by 'error' is set to the value of errno just after the I/O * error. */ int rdbSaveRio(rio *rdb, int *error, int flags, rdbSaveInfo *rsi) // rdb.c:1102 { if (rdbSaveInfoAuxFields(rdb,flags,rsi) == -1) goto werr; // rdb.c:1114 } /* Write a sequence of commands able to fully rebuild the dataset into * "filename". Used both by REWRITEAOF and BGREWRITEAOF. * * In order to minimize the number of commands needed in the rewritten * log Redis uses variadic commands when possible, such as RPUSH, SADD * and ZADD. However at max AOF_REWRITE_ITEMS_PER_CMD items per time * are inserted using a single command. */ int rewriteAppendOnlyFile(char *filename) // aof.c:1344 { // 对于AOF,传入的第三个参数rsi值为NULL, // 因此不会记录复制信息,这样进程重启需要全量复制。 if (rdbSaveRio(&aof,&error,RDB_SAVE_AOF_PREAMBLE,NULL) == C_ERR) { // aof.c:1367 } |
启动时调用顺序:
main(server.c:4003) -> loadDataFromDisk(server.c:3850) -> loadAppendOnlyFile(aof.c:673,当配置appendonly值为yes时) -> rdbLoadRio(rdb.c:1850) |
REdis AOF文件结构分析的更多相关文章
- Redis AOF文件
[Redis AOF文件] 1.关于AOF AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集. AOF 文件中的命令全部以 Redis 协议的格式来保存 ...
- 解决redis aof文件过大的问题
执行BGREWRITEAOF命令对redis的AOF进行重写 redis-cli BGREWRITEAOF 相关解释: Redis的AOF机制有点类似于Mysql binlog,是Redis的提供的一 ...
- redis aof文件过大问题
http://www.itnose.net/detail/6682725.html 最近新安装了一台redis,版本为redis-3.2.5 数据盘用的是固态硬盘. 之前用的是普通硬盘,redis日志 ...
- redis 持久化 如果 AOF 文件出错了,怎么办?
服务器可能在程序正在对 AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏. ...
- redis只加载AOF文件
如果同时配置写AOF和RDB两种文件,但在redis启动时,只会加载AOF,除非配置只写RDB,才会加载RDB文件,也因此AOF文件必须是全量数据,所以会越来越大,这缺点也将是redis优化的一个方向 ...
- redis 持久化策略、aof配置、测试、手动持久化、aof文件体积优化
redis持久化策略 1.数据文件.rdb 2.更新日志.aof 设置aof 1.命令方式config set appendonly noconfig rewrite2.配置文件方式 redis持久化 ...
- redis的redis.conf文件详解
常用的: GENERAL: daemonize yes 守护进程 port 6379 指定Redis监听端口 requirepass 1 设置认证密码为1 REPLICATION: slave ...
- 深入剖析 redis AOF 持久化策略
本篇主要讲的是 AOF 持久化,了解 AOF 的数据组织方式和运作机制.redis 主要在 aof.c 中实现 AOF 的操作. 数据结构 rio redis AOF 持久化同样借助了 struct ...
- redis AOF保存机制
网上说AOF有三种保存方式,不自动保存.每秒自动保存.每命令自动保存. 其中每秒自动保存这个看起来很美好,但是可能会被各种IO的时间所延迟,所以究竟是怎么判断每秒保存的,并不是太明白,故有此文. AO ...
随机推荐
- 三台linux集群hadoop,在此上面运行hive
---恢复内容开始--- 一,准备 先有三台linux,对hadoop集群的搭建. eddy01:开启一个hdfs的老大namenode,yarn的老大ResourceManager其中进程包括(No ...
- 实战ELK(3) Kibana安装与简单实用
第一步:下载 https://artifacts.elastic.co/downloads/kibana/kibana-6.5.1-x86_64.rpm 第二步:安装 1.安装 yum install ...
- 获取电脑的 SN 码
wmic bios get serialnumber
- IO密集型和计算密集型
我们常说的多任务或者单任务分为两种: IO密集型的任务 计算密集型的任务 IO密集型的任务或:有阻塞的状态,就是不一直会运行CPU(中间就一个等待状态,就告诉CPU 等待状态,这个就叫IO密集型 ...
- RocketMQ入门(Filter)_5
RocketMQ中存储的消息对于消费者来说,并不完全都是他们需要的,因此需要对消息进行过滤. 订阅Topic主题 ,选择Tags都是我们简单的过滤.Topic是大分类,Tags是二级分类. Rocke ...
- c/c++ 整数除预算保留小数
两个整数相除会自动省略小数点后的小数位即使下面这种: int a,int b; int a = 4; int b = 3; double d = a/b; d= 1.0000000; -------- ...
- Linux网络编程学习(五) ----- 信号(第四章)
1.基本概念 进程阻塞: 进程执行条件得不到满足,就自动放弃CPU资源而进入休眠状态,以等待条件满足,当条件满足时,系统就将控制权还给该进程进行未完成的操作 共享资源: 进程间协调使用的系统资源 锁定 ...
- Android Studio2.0 教程从入门到精通Windows版 - 入门篇
http://www.open-open.com/lib/view/open1468121363300.html 本文转自:深度开源(open-open.com)原文标题:Android Studio ...
- Python程序互斥体
Python程序互斥体 有时候我们需要程序只运行一个实例,在windows平台下我们可以很简单的用mutex实现这个目的. 在开始时,程序创建了一个命名的mutex,这个mutex可以被其他进 ...
- 使用rpm-build制作nginx的rpm包
2014-11-27 11:05:49 一.RPM包的分类 RPM有五种基本的操作功能:安装.卸载.升级.查询和验证. linux软件包分为两大类: (1)二进制类包,包括rpm安装包(一般分为i ...