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文件结构分析的更多相关文章

  1. Redis AOF文件

    [Redis AOF文件] 1.关于AOF AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集. AOF 文件中的命令全部以 Redis 协议的格式来保存 ...

  2. 解决redis aof文件过大的问题

    执行BGREWRITEAOF命令对redis的AOF进行重写 redis-cli BGREWRITEAOF 相关解释: Redis的AOF机制有点类似于Mysql binlog,是Redis的提供的一 ...

  3. redis aof文件过大问题

    http://www.itnose.net/detail/6682725.html 最近新安装了一台redis,版本为redis-3.2.5 数据盘用的是固态硬盘. 之前用的是普通硬盘,redis日志 ...

  4. redis 持久化 如果 AOF 文件出错了,怎么办?

    服务器可能在程序正在对 AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏. ...

  5. redis只加载AOF文件

    如果同时配置写AOF和RDB两种文件,但在redis启动时,只会加载AOF,除非配置只写RDB,才会加载RDB文件,也因此AOF文件必须是全量数据,所以会越来越大,这缺点也将是redis优化的一个方向 ...

  6. redis 持久化策略、aof配置、测试、手动持久化、aof文件体积优化

    redis持久化策略 1.数据文件.rdb 2.更新日志.aof 设置aof 1.命令方式config set appendonly noconfig rewrite2.配置文件方式 redis持久化 ...

  7. redis的redis.conf文件详解

    常用的: GENERAL: daemonize  yes  守护进程  port 6379 指定Redis监听端口 requirepass 1  设置认证密码为1 REPLICATION: slave ...

  8. 深入剖析 redis AOF 持久化策略

    本篇主要讲的是 AOF 持久化,了解 AOF 的数据组织方式和运作机制.redis 主要在 aof.c 中实现 AOF 的操作. 数据结构 rio redis AOF 持久化同样借助了 struct ...

  9. redis AOF保存机制

    网上说AOF有三种保存方式,不自动保存.每秒自动保存.每命令自动保存. 其中每秒自动保存这个看起来很美好,但是可能会被各种IO的时间所延迟,所以究竟是怎么判断每秒保存的,并不是太明白,故有此文. AO ...

随机推荐

  1. 实验二:Linux下Xen环境的安装

    实验名称: Linux下Xen环境的安装(centOS7) 实验环境: 本次实验基本是在centOS7的环境下完成,系统内核和系统版本如下: 实验要求: 为centOS7的环境下安装Xen的平台,能够 ...

  2. mysql5.7.18.1修改用户密码报错ERROR 1054 (42S22): Unknown column 'password' in 'field list'解决办法

    本意向修改一个用户的密码,网上搜到的命令为如下 mysql> update user set password=password(“新密码”) where user=”用户名”; 执行后报错 E ...

  3. oracle12c安装[INS-30131]异常

    接昨天写到的oracle12c安装异常解决办法. 解决这个问题百度到两种解决办法: 方法一 1.1.检查开启服务 控制面板 → 管理工具 → 服务 找到TCP/IP 和 Server 状态调为“启动” ...

  4. gentoo emerge L10N

    gentoo 中安装软件的时候 emerge 提示 USE 中有 语言包可选安装,使用 L10N 来设置,设置方法是在USE中使用 l10n_,比如说 l10n_zh_CN 来安装中文支持包.

  5. openstack网络

    OpenStack中neutron的2种ip.3种管理模式 Nova有固定IP和浮动IP的概念.固定IP被分发到创建的实例不再改变,浮动IP是一些可以和实例动态绑定和释放的IP地址. Nova支持3种 ...

  6. python学习笔记_week26

    note 一.CMDB -采集资产 -API -后台管理 -资产列表(CURD) -业务线列表(CURD) -用户列表(CURD) -组列表(CURD) ... ===>简单<=== 公共 ...

  7. Mybatis-spring 传统dao开发

    jdbc.properties jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/mybatis?chara ...

  8. Android Room 学习(一)

    Room简介 Room persistence库为SQLite提供了一个抽象层,以便在利用SQLite的全部功能的同时实现更强大的数据库访问. 该库可帮助您在运行应用程序的设备上创建应用程序数据的缓存 ...

  9. oracle 11g密码过期问题解决方法

    ORACLE 11G密码过期问题: 1.使用oracle用户进入sql编辑器中执行修改密码(原始密码,保持不变)的命令 sql>alter user 用户名 identified by &quo ...

  10. K8s之Etcd

    Etcd是一个开源的.高可用的.分布式的键值对数据存储系统,提供共享配置.服务的注册和发现.etcd与zookeeper相比算是轻量级系统,两者的一致性协议也一样,etcd的raft比zookeepe ...