本文將通過分析代碼來介紹Redis的啟動過程,通過查看Redis 的啟動指令碼,得知Redis的啟動時從Redis.c的main方法開始的。Redis啟動可以分為以下幾個步驟:
1.初始化Redis伺服器全域配置
2.重設伺服器Save參數(具體下文詳解)和載入設定檔
3.初始化伺服器
4.載入資料庫
5.開始網路監聽
一,初始化Redis伺服器全域配置。這一步驟主要是主要是根據Redis.h中設定的Static值來初始化Redis伺服器配置,這裡設定是Redis伺服器的預設配置。如:
·TCP Port,Redis Client的預設Timeout;
·Redis預設的資料庫數目;
·Redis Append 持久化方式的參數設定;
·Redis的所支援的各種資料結構的預設值的設定;
·Redis記憶體Swap相關設定;
·Redis Master & Slave相關的配置;
·Redis Command Table初始化。
二,載入設定檔:
這一步是通過讀取的設定檔來對Redis伺服器進行設定,將會覆蓋上一步的某些預設設定。開啟下載下來的Redis原始碼,我們可以看到其根目錄下有一個預設的設定檔redis.conf。需要注意的是,如果在啟動Redis的時候沒有指定設定檔,則Redis伺服器在啟動的時候是不會載入這個預設的設定檔進行配置的。而且這個預設的設定檔和第一步中得全域預設預設配置不盡相同,比如針對Redis的Append模式的資料儲存策略的配置,redis.conf裡面的設定是:
save 900 1 -------15分鐘內一次更新
save 300 10 ------5分鐘內10次更新
save 60 10000 ---1分鐘內10000次更新。
而上一步裡面的預設預設配置確實:
save 60*60 1 -------一個小時內1次更新
save 300 100 ------5分鐘內100次更新
save 60 10000 ---1分鐘內10000次更新。
因此我們在啟動Redis的時候如果預設配置不能滿足要求,則需要指明設定檔進行配置。
三,初始化伺服器:
初始化伺服器是在initServer()方法中完成的,次方法利用上兩步設定的參數進一步初始化伺服器:
·建立用來維護clients和slaves的list
·建立共用對象。redisObject這個struct裡有個變數叫做refcount,這個變數就是用來實現共用的。Redis的對象目前Redis只支援共用StringObject。Redis的共用對象有兩大類比:第一類:Redis server的各種操作需要經常用到的各類對象,如:Redis Command的分隔字元 "\r\n",用於Redis command的reply的"+OK\r\n"或者"-ERR\r\n"等對象,因為在Redis的各種操作這類對象要被頻繁使用,所以就在啟動Redis的時候建立好,然後共用這些對象,減少時間成本和空間成本;第二,類的共用對象就是對應於數位StringObject,如:Set "olylakers1" 1234; Set "olylakes2" 1234;在Redis內部,"olylakers1"和"olylakers2"這兩個key都指向由數字1234轉化的StringObject。這樣在海量資料和特定儲存內容下,可以節省大量的記憶體空間。可用通過REDIS_SHARED_INTEGERS這個參數來指定Redis啟動的時候建立多少個第二類共用對象,預設的參數是10000,即建立的StrongObject個取值範圍是0-9999之間。
·建立Pub/Sub通道
·初始化網路監聽EventLoop的相關內容,如eventLoop,timeEvent,fileEvent等
·如果開啟了VM,則初始化虛擬記憶體相關的IO/Thread
四,載入資料:
根據配置的不同,Redis載入資料的源也不一樣,如果在設定檔裡設定了appendonly yes(預設是no),那麼就從appendfile載入資料,反之則從RedisDb載入資料
·從appendfile載入資料:我們先來看一下appendfile的內容是什麼。下面的一條記錄摘取自appendfile:SET $9 olylakers $3 oly。很顯,appendfile儲存的就是redis server接收到的各種命令,那麼從appendfile載入資料就是redis server從appenfile裡面讀取這些命令的記錄,然後重新把這些命令執行一遍即可。需要注意的是,如果開啟了VM,那麼在從appendfile載入資料的時候可能要涉及swap操作。
·從redisdb載入資料:如果沒有開啟appendonly,那麼則需要從db file載入資料到記憶體,其過程是:
1.通過處理select命令,選擇DB
2.然後從db file讀取key和value
3.檢查key是否到期,如果到期則跳過這個key,如果不到期,則把資料Add到對應的db的dict中
4.如果開啟了VM,則從db file中load資料,也可能涉及到swap操作
五,開始網路監聽:
Redis的網路監聽沒有採用libevent等,而是自己實現了一套簡單的機遇event驅動的API,具體見ae.c。