Redis数据持久化机制AOF原理分析二(一)

2014-11-24 11:49:16 · 作者: · 浏览: 0

本文所引用的源码全部来自Redis2.8.2版本。

Redis AOF数据持久化机制的实现相关代码是redis.c, redis.h, aof.c, bio.c, rio.c, config.c

在阅读本文之前请先阅读Redis数据持久化机制AOF原理分析之配置详解文章,了解AOF相关参数的解析,文章链接

http://blog.csdn.net/acceptedxukai/article/details/18135219

接着上一篇文章,本文将介绍Redis是如何实现AOF rewrite的。

转载请注明,文章出自http://blog.csdn.net/acceptedxukai/article/details/18181563

AOF rewrite的触发机制

如果Redis只是将客户端修改数据库的指令重现存储在AOF文件中,那么AOF文件的大小会不断的增加,因为AOF文件只是简单的重现存储了客户端的指令,而并没有进行合并。对于该问题最简单的处理方式,即当AOF文件满足一定条件时就对AOF进行rewrite,rewrite是根据当前内存数据库中的数据进行遍历写到一个临时的AOF文件,待写完后替换掉原来的AOF文件即可。

Redis触发AOF rewrite机制有三种:

1、Redis Server接收到客户端发送的BGREWRITEAOF指令请求,如果当前AOF/RDB数据持久化没有在执行,那么执行,反之,等当前AOF/RDB数据持久化结束后执行AOF rewrite

2、在Redis配置文件redis.conf中,用户设置了auto-aof-rewrite-percentage和auto-aof-rewrite-min-size参数,并且当前AOF文件大小server.aof_current_size大于auto-aof-rewrite-min-size(server.aof_rewrite_min_size),同时AOF文件大小的增长率大于auto-aof-rewrite-percentage(server.aof_rewrite_perc)时,会自动触发AOF rewrite

3、用户设置“config set appendonly yes”开启AOF的时,调用startAppendOnly函数会触发rewrite

下面分别介绍上述三种机制的处理.

接收到BGREWRITEAOF指令

void bgrewriteaofCommand(redisClient *c) {
    //AOF rewrite正在执行,那么直接返回
    if (server.aof_child_pid != -1) {
        addReplyError(c,"Background append only file rewriting already in progress");
    } else if (server.rdb_child_pid != -1) {
        //AOF rewrite未执行,但RDB数据持久化正在执行,那么设置AOF rewrite状态为scheduled
        //待RDB结束后执行AOF rewrite
        server.aof_rewrite_scheduled = 1;
        addReplyStatus(c,"Background append only file rewriting scheduled");
    } else if (rewriteAppendOnlyFileBackground() == REDIS_OK) {
        //直接执行AOF rewrite
        addReplyStatus(c,"Background append only file rewriting started");
    } else {
        addReply(c,shared.err);
    }
}
当AOF rewrite请求被挂起时,在serverCron函数中,会处理。
/* Start a scheduled AOF rewrite if this was requested by the user while
     * a BGSAVE was in progress. */
    // 如果用户执行 BGREWRITEAOF 命令的话,在后台开始 AOF 重写
    //当用户执行BGREWRITEAOF命令时,如果RDB文件正在写,那么将server.aof_rewrite_scheduled标记为1
    //当RDB文件写完后开启AOF rewrite
    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1 &&
        server.aof_rewrite_scheduled)
    {
        rewriteAppendOnlyFileBackground();
    }

Server自动对AOF进行rewrite

在serverCron函数中会周期性判断
/* Trigger an AOF rewrite if needed */
         //满足一定条件rewrite AOF文件
         if (server.rdb_child_pid == -1 &&
             server.aof_child_pid == -1 &&
             server.aof_rewrite_perc &&
             server.aof_current_size > server.aof_rewrite_min_size)
         {
            long long base = server.aof_rewrite_base_size  
                            server.aof_rewrite_base_size : 1;
            long long growth = (server.aof_current_size*100/base) - 100;
            if (growth >= server.aof_rewrite_perc) {
                redisLog(REDIS_NOTICE,"Starting automatic rewriting of AOF on %lld%% growth",growth);
                rewriteAppendOnlyFileBackground();
            }
         }

config set appendonly yes

当客户端发送该指令时,config.c中的configSetCommand函数会做出响应,startAppendOnly函数会执行AOF rewrite
if (!strcasecmp(c->argv[2]->ptr,"appendonly")) {
	int enable = yesnotoi(o->ptr);

	if (enable == -1) goto badfmt;
	if (enable == 0 && server.aof_state != REDIS_AOF_OFF) {//appendonly no 关闭AOF
		stopAppendOnly();
	} else if (enable && server.aof_state == REDIS_AOF_OFF) {//appendonly yes rewrite AOF
		if (startAppendOnly() == REDIS_ERR) {
			addReplyError(c,
				"Unable to turn on AOF. Check server logs.");
			return;
		}
	}
}
int st