Redis分析系列:啟動載入過程

來源:互聯網
上載者:User

從本篇文章開始(命名為Redis分析系列),將會通過分析Redis的原始碼(以Redis 2.2.0 RC1為準),來對它的內部實現做一些探討。本文主要介紹Redis啟動載入過程,總體上可以分為如下幾步:

1. 初始化全域伺服器配置

2. 載入設定檔(如果指定了設定檔,否則使用預設配置)

3. 初始化伺服器

4. 載入資料庫

5. 網路監聽

整個啟動載入過程如下圖所示:

下面對於上圖中的各個步驟一些介紹,有些部分(如資料庫載入、網路監聽)會在後面單獨用一篇文章詳細說明。 初始化全域伺服器配置

初始化全域伺服器配置通過initServerConfig()函數完成,主要是初始化server變數,它是一個redisServer的結構類型:

struct redisServer server;

初始化的內容包括下面幾個方面:

1. 網路監聽相關,如綁定地址,TCP連接埠等 
2. 虛擬記憶體相關,如swap檔案、page大小等 
3. 儲存機制,多長時間內有多少次更新才進行儲存 
4. 複製相關,如是否是slave,master地址、連接埠 
5. Hash相關設定 
6. 初始化命令表

如其中的儲存機制中,伺服器初始化策略為:

// 1小時內1次更新appendServerSaveParams(60*60,1);// 5分鐘內100次更新appendServerSaveParams(300,100);// 1分鐘內10000次更新appendServerSaveParams(60,10000);

如果在啟動伺服器時,指定了設定檔,則會在下面的“載入設定檔”步驟中,根據設定檔內容,更改其中的某些伺服器配置。 載入設定檔

如果指定了設定檔,Redis使用loadServerConfig()函數載入設定檔,整個過程沒什麼可以說的,無非是使用標準I/O庫開啟設定檔,迴圈讀取每一行然後覆蓋上一步進行的預設配置。

這裡有一點需要注意的是,下載Redis後程式碼封裝中有一個預設設定檔,如果啟動Redis伺服器時,不指定設定檔,Redis不會使用這個預設檔案的配置,而是使用上一步“初始化全域伺服器配置”中的配置。在預設設定檔中提供的配置項與上一步預設初始化的配置有些事不一樣的,所以如果沒有指定設定檔,千萬不能認為Redis的行為會按照預設設定檔進行,最典型的一個例子,在預設設定檔中的資料儲存策略是:

# 15分鐘內1次更新save 900 1# 5分鐘內100次更新save 300 10# 1分鐘內10000次更新save 60 10000

而預設初始化的全域配置中資料儲存策略:

// 1小時內1次更新appendServerSaveParams(60*60,1);// 5分鐘內100次更新appendServerSaveParams(300,100);// 1分鐘內10000次更新appendServerSaveParams(60,10000);
初始化伺服器

初始化伺服器的工作在initServer()函數中,主要是完成前面未完成的工作,繼續對server變數初始化,如設定訊號處理、建立clients、slaves列表,建立Pub/Sub通道列表,同時還會建立共用對象:

shared.crlf = createObject(REDIS_STRING,sdsnew("\r\n"));shared.ok = createObject(REDIS_STRING,sdsnew("+OK\r\n"));shared.err = createObject(REDIS_STRING,sdsnew("-ERR\r\n"));shared.emptybulk = createObject(REDIS_STRING,sdsnew("$0\r\n\r\n"));

最後,如果啟用了虛擬記憶體機制,還需要初始化虛擬記憶體相關,如Thread I/O等。 載入資料庫

在完成了上面的所有的初始化工作之後,Redis開始載入資料到記憶體中,如果啟用了appendonly了(不知道這個參數做什麼的,請先看設定檔篇),則Redis從appendfile載入資料,否則就從dbfile載入資料。

1. 從appendfile中載入資料:loadAppendOnlyFile()函數

在此之前,我們先來看一下appendfile裡面儲存了什麼,如我執行了下面兩條命令(記得在設定檔中開啟appendonly):

redis> SET mykey001 myvalue001OKredis> GET mykey001"myvalue001"

使用cat命令查看appendonly.aof檔案內容:

$ cat appendonly.aof*2$6SELECT$10*3$3SET$8mykey001$10myvalue001

嗯,相信大家都能看明白(看不明白的請先看這篇文章),在appendonly.aof檔案中儲存的正是從用戶端發過來的請求命令,還可以看到對於GET命令,並沒有儲存。既然appendonly.aof中儲存了所有寫入資料的請求命令,那麼在載入資料的時候只要重新執行一遍這些命令即可。

事實上Redis也正是這麼做的,在開始載入之前暫時關閉appendonly,然後Redis建立一個假的Redis用戶端:

server.appendonly = 0;fakeClient = createFakeClient();startLoading(fp);

然後讀取appendonly.aof檔案中的命令,在假的Redis用戶端內容中執行,同時伺服器也不對該用戶端做任何應答:

fakeClient->argc = argc;fakeClient->argv = argv;cmd->proc(fakeClient);/* The fake client should not have a reply */redisAssert(fakeClient->bufpos == 0 && listLength(fakeClient->reply) == 0);

如果載入過程中實體記憶體不夠用,並且Redis開啟了VM,則還需要處理swap操作,最後載入完成後重新設定appendonly標誌。

2. 從dbfile中載入資料:rdbLoad()函數

如果Redis沒有開啟appendonly,就需要從資料庫檔案中載入資料到記憶體,基本步驟如下:

a. 處理SELECT命令,即選擇資料庫 
b. 讀取key 
c. 讀取value 
d. 檢測key是否到期 
e. 添加新的對象到雜湊表 
f. 設定到期時間(如果需要) 
g. 如果開啟了VM,處理swap操作 網路監聽

在完成了初始化配置和資料載入後,Redis啟動監聽。Redis的網路程式庫沒有使用libevent或者libev,而是作者自己實現的一個非常輕量級的庫(主要實現在ae.c檔案中),這部分內容在後面分析Redis的網路程式庫的時候單獨寫篇文章。

通過本文,介紹了Redis的啟動載入過程,希望對大家有所協助。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.