1. 程式人生 > 實用技巧 >REDIS6.0原始碼閱讀(二)REDIS-SERVER啟動主流程之initServerConfig

REDIS6.0原始碼閱讀(二)REDIS-SERVER啟動主流程之initServerConfig


在redis-server的初始化過程中,會從引數(redis.conf檔案中讀取使用者的配置資訊),還包含有一些諸如設定時區引數、設定記憶體溢位的回撥函式等,比較重要的是initServerConfig,initServerConfig主要包含有一些基礎引數的讀取和配置,如:

  • updateCachedTime(1);//儲存一個unix的全域性變數,用來儲存時間,呼叫起來要比呼叫time方法快
  • getRandomHexChars(server.runid,CONFIG_RUN_ID_SIZE);//設定伺服器執行的ID
  • server.runid[CONFIG_RUN_ID_SIZE] = '\0';//為執行ID後面加換行
  • changeReplicationId();//用一個新生成的隨機的ID替代當前server的例項的ID
  • //以及一些最基本的引數

同時通過populateCommandTable();方法設定一些最基礎的命令列,如我們常用的setget命令等。原始碼中寫道:初始化的時候要初始一部分命令碼及其對應的回撥,當然可以通過redis.conf來修改命令碼的內容,亦即我們可以通過修改redis.conf檔案來實現對命令列的重新命名操作。

可以看出命令列的設定是依賴於結構體redisCommandTable的,通過閱讀我們可以發現該結構體其實為命令碼及其對應的命令處理函式的一一對應關係,下面示例程式碼以set

命令和setCommand方法對應關係做一個說明:

struct redisCommand redisCommandTable[] = {
    ......
    /* Note that we can't flag set as fast, since it may perform an
     * implicit DEL of a large key. */
    {"set",setCommand,-3,
     "write use-memory @string",
     0,NULL,1,1,1,0,0,0}
    ......
}

而處理命令對應的處理函式卻藏在結構體redisCommand

中:

struct redisCommand {
    char *name;//命令的名字,如set
    redisCommandProc *proc;//命令執行的函式,如setCommand
    int arity;//引數的個數
    char *sflags; //字串的標誌位
    uint64_t flags; //真實的標誌位
    /* Use a function to determine keys arguments in a command line.
     * Used for Redis Cluster redirect. */
    //下面的內容涉及到叢集部署之後,命令對應的方法如何路由的問題,後面閱讀到叢集相關內容後會補充
    redisGetKeysProc *getkeys_proc;//當開啟叢集的時候,需要根據key值來確認路由到哪個server
    /* What keys should be loaded in background when calling this command? */
    int firstkey; //第一個key值
    int lastkey;  //最後一個key值
    int keystep;  //從第一個key值到最後一個key值所走的步數
    long long microseconds, calls;
    int id;//此ID比較關鍵,為redis 6.0版本之後新增的功能,即ACL子系統對不同使用者所擁有的命令列許可權的控制
};

介紹完上面兩個比較關鍵的結構體後,我們仍舊以set及其對應的setCommand方法為例,在populateCommandTable()方法中,我們會根據redisCommandTable表中的內容一個個進行初始化,當初始化到set的時候,我們gdb除錯跟蹤到其內容如下:

即所有的命令都是通過類似的形式來進行其對應的命令處理函式的設定,命令對應的命令處理函式,在server.h檔案中可以查詢到,大部分都是顧名思義的:

......
void setCommand(client *c);
.....

當我們redis-server啟動之後,redis-cli通過set命令執行的時候,其堆疊呼叫流程如下:

當我們redis-server啟動之後,redis-cli通過set命令執行的時候,其堆疊呼叫流程如下:
我們通過程式碼跟蹤到call這個回撥,可以看到從client傳過來的命令的名字為set,此時根據已經設定好的set對應setCommand,即下一步的執行為setCommand:

小結:本文主要介紹initServerConfig初始化配置資訊的一些內容,著重描述了populateCommandTable()方法在初始化命令及其對應的命令處理函式之間的初始化,並通過set命令及setCommand方法的呼叫來說明這個過程,當然,內容中涉及到ACL子系統相關的內容暫未做介紹,setCommand的對應呼叫流程也未作具體說明,後面相關內容都會繼續補充。