1. 程式人生 > >一個小改進,解決Redis資料線上載入大痛點

一個小改進,解決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(
c,"Can't BGSAVE while AOF log rewriting is in progress"); } else if (c->argc != 2){ addReply(c,shared.syntaxerr); return; } else if (loadAppendOnlyFile(c->argv[1]->ptr) == REDIS_OK) { addReplyStatus(c,"online loadaof started,Do not repeat!!!"); } else { addReply(
c,shared.err); } }

在執行 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的快捷操作。