redis 启动加载mysql_Redis分析系列:启动加载过程
從本篇文章開始(命名為Redis分析系列),將會通過分析Redis的源代碼(以Redis 2.2.0 RC1為準),來對它的內部實現做一些探討。本文主要介紹Redis啟動加載過程,總體上可以分為如下幾步:
1. 初始化全局服務器配置
2. 加載配置文件(如果指定了配置文件,否則使用默認配置)
3. 初始化服務器
4. 加載數據庫
5. 網絡監聽
整個啟動加載過程如下圖所示:
下面對于上圖中的各個步驟一些介紹,有些部分(如數據庫加載、網絡監聽)會在后面單獨用一篇文章詳細說明。
初始化全局服務器配置
初始化全局服務器配置通過initServerConfig()函數完成,主要是初始化server變量,它是一個redisServer的結構類型:
structredisServer 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 myvalue001
OK
redis> GET mykey001
"myvalue001"
使用cat命令查看appendonly.aof文件內容:
$ cat appendonly.aof
*2
$6
SELECT
$1
0
*3
$3
SET
$8
mykey001
$10
myvalue001
嗯,相信大家都能看明白(看不明白的請先看這篇文章),在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的啟動加載過程,希望對大家有所幫助。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的redis 启动加载mysql_Redis分析系列:启动加载过程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux查看服务器版本号(linux查
- 下一篇: mysql+误操作怎么恢复_Mysql误