本文所引用的源码全部来自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