本文所引用的源碼全部來自Redis2.8.2版本。
Redis的配置文件爲redis.conf, 對配置文件的解析代碼見config.c
原創文章轉載請註明,本文來自http://blog.csdn.net/acceptedxukai/article/details/18135219
AOF實現機制簡介
AOF 即Append Only File,實現機制:Redis將數據庫做個快照,遍歷所有數據庫,將數據庫中的數據還原爲跟客戶端發送來的指令的協議格式的字符串,然後Redis新建一個臨時文件將這些快照數據保存,待快照程序結束後將臨時文件名修改爲正常的aof文件名,原有的文件則自動丟棄,由於在快照進行的過程中可能存在新增的命令修改了數據庫中的數據,則在快照程序結束後需要將新修改的數據追加到aof文件中,後續的從客戶端過來的命令都會不斷根據不同的安全級別寫到磁盤裏面去。這樣就支持了實時的持久化,只是可能會有短時間內的數據丟失,對一般系統還是可以容忍的。
配置文件redis.conf中有關AOF參數配置解釋
appendonly
含義:Redis Server是否開啓AOF持久化機制
在config.c函數loadServerConfigFromString解析代碼爲
if (!strcasecmp(argv[0],"appendonly") && argc == 2) { int yes; if ((yes = yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; } server.aof_state = yes ? REDIS_AOF_ON : REDIS_AOF_OFF; }
appendfsync
含義:Redis將OS數據緩衝區中數據刷新到磁盤的策略
# appendfsync always 只要有新添加的數據就fsync
appendfsync everysec 支持延遲fsync
# appendfsync no 不需要fsync
config.c中解析代碼
if (!strcasecmp(argv[0],"appendfsync") && argc == 2) {//AOF fsync策略 if (!strcasecmp(argv[1],"no")) { server.aof_fsync = AOF_FSYNC_NO; } else if (!strcasecmp(argv[1],"always")) { server.aof_fsync = AOF_FSYNC_ALWAYS; } else if (!strcasecmp(argv[1],"everysec")) { server.aof_fsync = AOF_FSYNC_EVERYSEC; } else { err = "argument must be 'no', 'always' or 'everysec'"; goto loaderr; } }
no-appendfsync-on-rewrite
含義:當rewrite AOF子進程或RDB子進程正在執行時,Server是否支持fsync,即當新修改的數據寫入AOF文件後,是否將數據刷新到硬盤
config.c中解析代碼
server.aof_no_fsync_on_rewrite控制該機制的實現代碼在aof.c的flushAppendOnlyFile函數中,具體代碼爲if (!strcasecmp(argv[0],"no-appendfsync-on-rewrite") && argc == 2) { if ((server.aof_no_fsync_on_rewrite= yesnotoi(argv[1])) == -1) { err = "argument must be 'yes' or 'no'"; goto loaderr; } }
//如果不支持fsync,或者aof rdb子進程正在運行,那麼直接返回, //但是數據已經寫到aof文件中,只是沒有刷新到硬盤 if (server.aof_no_fsync_on_rewrite && (server.aof_child_pid != -1 || server.rdb_child_pid != -1)) return;
appendfilename
含義:AOF的文件名
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb這兩個配置就暫不解釋,見下面redisServer結構體中中有關AOF參數的註釋
redisServer數據結構中有關AOF的參數
struct redisServer { ………… /* AOF persistence */ int aof_state; /* REDIS_AOF_(ON|OFF|WAIT_REWRITE) */ int aof_fsync; /* Kind of fsync() policy */ char *aof_filename; /* Name of the AOF file */ int aof_no_fsync_on_rewrite; /* Don't fsync if a rewrite is in prog. */ int aof_rewrite_perc; /* Rewrite AOF if % growth is > M and... */ off_t aof_rewrite_min_size; /* the AOF file is at least N bytes. */ aof文件最小字節數 off_t aof_rewrite_base_size; /* AOF size on latest startup or rewrite. */ 上一次aof文件的大小 off_t aof_current_size; /* AOF current size. */ 當前aof文件的大小 int aof_rewrite_scheduled; /* Rewrite once BGSAVE terminates. */ pid_t aof_child_pid; /* PID if rewriting process */ 子進程的pid list *aof_rewrite_buf_blocks; /* Hold changes during an AOF rewrite. */ sds aof_buf; /* AOF buffer, written before entering the event loop */ int aof_fd; /* File descriptor of currently selected AOF file */ aof文件描述符 int aof_selected_db; /* Currently selected DB in AOF */ time_t aof_flush_postponed_start; /* UNIX time of postponed AOF flush */ time_t aof_last_fsync; /* UNIX time of last fsync() */ time_t aof_rewrite_time_last; /* Time used by last AOF rewrite run. */ time_t aof_rewrite_time_start; /* Current AOF rewrite start time. */ int aof_lastbgrewrite_status; /* REDIS_OK or REDIS_ERR */ unsigned long aof_delayed_fsync; /* delayed AOF fsync() counter */ int aof_rewrite_incremental_fsync;/* fsync incrementally while rewriting? */ ………… }
字符串aof_buf與鏈表aof_rewrite_buf_blocks分別是追加AOF文件與rewrite AOF文件後處理差異數據的重要參數
initServerConfig函數對AOF參數的初始化及註釋
其中aof_current_size參數未初始化,該值的初始化在Server啓動加載AOF文件數據時初始化。server.aof_state = REDIS_AOF_OFF; //AOF文件是否開啓 server.aof_fsync = REDIS_DEFAULT_AOF_FSYNC; //fsync策略,默認爲每秒fsync server.aof_no_fsync_on_rewrite = REDIS_DEFAULT_AOF_NO_FSYNC_ON_REWRITE;//aof rdb子進程運行中是否支持fsync,即寫入AOF文件後,將數據刷新到硬盤 server.aof_rewrite_perc = REDIS_AOF_REWRITE_PERC; //自動rewrite增量值 server.aof_rewrite_min_size = REDIS_AOF_REWRITE_MIN_SIZE; //AOF文件最小字節數 server.aof_rewrite_base_size = 0; //自動rewrite計算aof文件增量的基數,等於上一次aof文件的字節數 server.aof_rewrite_scheduled = 0; //rewrite任務計劃,當客戶端發送bgrewriteaof指令,如果當前rewrite子進程正在執行,那麼將客戶端請求的bgrewriteaof變爲計劃任務,待AOF子進程結束後執行rewrite server.aof_last_fsync = time(NULL); //最近fsync數據到硬盤時間 server.aof_rewrite_time_last = -1; //rewrite持續的時間 server.aof_rewrite_time_start = -1; //rewrite開始的時間 server.aof_lastbgrewrite_status = REDIS_OK; //rewrite後的狀態 server.aof_delayed_fsync = 0; //延遲fsync到硬盤的次數 server.aof_fd = -1; //AOF文件描述符 server.aof_selected_db = -1; /* Make sure the first time will not match */ server.aof_flush_postponed_start = 0; //上次推遲fsync到硬盤的時間 server.aof_rewrite_incremental_fsync = REDIS_DEFAULT_AOF_REWRITE_INCREMENTAL_FSYNC;//rewrite AOF文件時是否採用增量式fsync
小結
本文就是簡單介紹Redis中有關AOF機制實現的相關參數的意義,方便對接下來AOF數據持久化機制的理解,AOF機制的實現比較複雜,大致分爲Server啓動加載AOF文件數據、將新的數據追加到AOF文件中、自動rewrite AOF文件、客戶端請求BGREWRITEAOF指令四個部分,下面的博客將介紹這四個部分的實現。