直奔主題,當啓動Redis的時候,Redis執行了哪些操做?git
假設Redis安裝在了/usr/local/目錄下,那麼啓動Redis是經過執行/usr/local/bin/redis-server -c xxx.conf
的方式執行。
redis-server是一個經過編譯server.c文件生成的程序,所以想了解redis是怎麼啓動的,應該從server.c/main函數入手。github
具體代碼可見:server.credis
閱讀main函數,能夠知道,整個啓動大體分爲五個步驟:初始化server結構體、從配置文件夾在加載參數、初始化服務器、載入持久化文件、開始監聽事件。數據庫
redis用redisServer結構體來保存服務器的屬性和信息,在server.c文件中,定義了一個全局服務器變量:服務器
struct redisServer server;
另外,還定義了一個redis命令表,表裏包含了命令以及命令對應的函數:數據結構
struct redisCommand redisCommandTable;
在main函數裏,redis先調用initServerConfig函數初始化server結構體。函數
main函數調用initServerConfig函數爲server的屬性設置一些默認值,好比:oop
服務器的運行IDspa
redis使用的默認端口號,是在server.h定義的CONFIG_DEFAULT_SERVER_PORT = 6379日誌
LRU時鐘
主從備份相關參數
命令表
慢查詢參數
接着會保存當前執行的路徑和參數,爲以後的服務器重啓使用相同的參數作準備:
server.executable = getAbsolutePath(argv[0]); server.exec_argv = zmalloc(sizeof(char*)*(argc+1)); server.exec_argv[argc] = NULL; for (j = 0; j < argc; j++) server.exec_argv[j] = zstrdup(argv[j]);
redis的啓動參數有不少,其中一個是指定配置文件。初始化server結構體後,大部分的屬性都會設置到結構體了,可是有部分參數能夠經過配置文件重現設置,好比redis的端口號。
初始化完server結構體後,函數會判斷是否有指定配置文件,若是有,調用loadServerConfig函數,從配置文件加載相關的配置,把配置文件對應的參數設置到server結構體。
讀取配置文件加載參數的流程以下:
- 一、分割參數項
- 二、跳過空行和註釋行
- 三、逐項檢查,若是參數合法,設置配置值到server屬性
至此,redisServer大部分屬性已經設置好,server還有不少數據結構沒有初始化,initServer函數就繼續接下來的初始化工做。
main函數會調用initServer函數初始化服務器狀態,好比:
進程ID
客戶端鏈表
從庫鏈表
爲經常使用值建立共享對象
初始化事件循環器
打開TCP開始監聽套接字
建立服務器的數據庫,並初始化內部狀態
爲serverCron定時器建立時間事件定時器
若是開啓了AOF,打開AOF文件,以後恢復數據時須要用到
初始化慢查詢日誌模塊
初始化後臺IO模塊
初始化完服務器的狀態後,服務器已經處於一個可啓動狀態,由於redis有持久化特性,服務器還須要加載相應的文件來還原以前數據庫的數據。
判斷Redis當前開啓了哪一種模式,若是是AOF,則經過AOF還原數據庫的數據,不然,載入RDB文件,經過RDB文件還原數據庫的數據。
main函數會設置beforeSleep和afterSleep回調函數,而後調用aeMain函數啓動事件循環器,開始監聽事件。aeMain函數是一個死循環,不斷的監聽新請求的到來。
/* * server啓動後,main函數的最終步驟,不斷地調用beforesleep和aeProcessEvents */ void aeMain(aeEventLoop *eventLoop) { eventLoop->stop = 0; while (!eventLoop->stop) { if (eventLoop->beforesleep != NULL) eventLoop->beforesleep(eventLoop); aeProcessEvents(eventLoop, AE_ALL_EVENTS|AE_CALL_AFTER_SLEEP); } }
綜上所述,服務器整個啓動簡化流程圖以下:
原創文章,文筆有限,才疏學淺,文中如有不正之處,萬望告知。
更多精彩內容,請關注我的公衆號。