一個小改進,解決Redis資料線上載入大痛點
作者介紹
顧偉濤,曾任職於百度、奇虎360,現為杭州銘師堂教育資深DBA,擅長資料庫監控、備份、高可用架構設計和自動化運維,對Redis和MongoDB方面有深入研究,關注分散式儲存、大資料儲存、訊息佇列、搜尋引擎等後端技術。
前言
在使用Redis載入資料過程中存在一個問題,就是必須要重啟Redis服務,如果是Redis主從複製架構,這樣載入資料,是一件很麻煩的事情,筆者根據Redis啟動時載入資料的思想,對Redis進行了改進,實現了線上載入資料,在這裡和大家一起探討下。
設計與實現
本文以Redis 3.0.7為例,根據Redis在啟動過程中,載入資料的邏輯,為Redis增加了2個命令,分別為LOADAOF和LOADRDB,分別實現線上載入aof和rdb檔案。
在執行 LOADAOF aofile時候,呼叫 loadAppendOnlyFile函式,載入aof檔案資料。具體實現如下:
src/aof.c
新增如下函式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void loadaofCommand(RedisClient *c) { if (server.rdb_child_pid != -1) { addReplyError(c,"Background save already in progress"); } else if (server.aof_child_pid != -1) { addReplyError( |
在執行 LOADRDB 時候,呼叫函式rdbLoad,載入rdb檔案。
src/rdb.c
新增如下函式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void loadrdbCommand(RedisClient *c) { if (server.rdb_child_pid != -1) { addReplyError(c,"Background save already in progress"); } else if (server.aof_child_pid != -1) { addReplyError(c,"Can't BGSAVE while AOF log rewriting is in progress"); } else if (c->argc != 2){ addReply(c,shared.syntaxerr); return; } else if (rdbLoad(c->argv[1]->ptr) == REDIS_OK) { addReplyStatus(c,"online loadrdb started,Do not repeat !!!"); } else { addReply(c,shared.err); } } |
src/Redis.c
在函式 struct RedisCommand RedisCommandTable[]
新增如下一行:
1 2 | {"loadaof",loadaofCommand,2,"ar",0,NULL,0,0,0,0,0}, {"loadrdb",loadrdbCommand,2,"ar",0,NULL,0,0,0,0,0}, |
src/Redis.h
在 void bgsaveCommand(RedisClient *c); 下面加入如下兩行:
1 2 | void loadrdbCommand(RedisClient *c); void loadaofCommand(RedisClient *c); |
src/help.h
在函式 struct commandHelp
新增如下內容:
1 2 3 4 5 6 7 8 9 10 | { "LOADAOF", "aof filename", "load aof file online", 9, "3.0.7"}, { "LOADRDB", "rdb filename", "load rdb file online,which can not repeat !!!", 9, "3.0.7"} |
執行以下命令編譯Redis
# cd Redis-3.0.7
# make && make PREFIX=/usr/local/Redis30 install
測試結果
可以看出,不重啟Redis,可以載入資料了。
應用場景
1、線上資料匯入到測試Redis
一般開發由類似需求,用於分析問題和測試。
2、恢復資料
如果Redis出現誤操作,可以執行線上載入資料,尤其是在sentinel(s)+Redis主從複製架構中,該方法更加漸變。
注意點
1、如果是Redis主從複製,在主庫線上載入aofile/rdbfile時,從庫上也需要存在這些檔案,否則從庫報錯退出。
2、執行線上載入操作時候,同樣的檔案內容,不要重複執行,否則從庫異常退出。
如果主庫重複執行loadrdb 時候,主庫也會異常退出。
該方案還存在著不足之處,在這裡只做拋磚引玉,希望和大家一起探討改進,便於DBA的快捷操作。