天天看點

對于redis底層架構的了解(一)

近期學習了redis底層架構,好多東西之前都沒聽說過,算是大開眼界了。

先梳理下redis正常的通訊流程吧

首先伺服器啟動都有主函數main,這個main函數就在redis.c裡

首先是initserverconfig(),在這裡初始化了redisserver基本的配置資訊,

接着調用loadServerConfig(char *filename) 對 server 全局變量重新初始化。

然後是調用daemonize(),實作守護程序,脫離了控制台,是這個程序

成為獨立的首領程序

接下來是initServer(),這個過程很重要,完成了事件驅動的注冊和一些

回調函數的綁定,回頭仔細說這個函數裡面的功能

初始化伺服器過後aeSetBeforeSleepProc(),設定了伺服器休眠之前會

調用beforeSleep函數

然後進入主要的事件輪詢函數 aeMain(server.el),在這裡完成事件的派發

最後事件輪詢過後我們調用aeDeleteEventLoop,釋放之前開辟的記憶體,

結束程序。

中間略去一些瑣碎的過程,我們總結一下

initserverconfig() ----> loadServerConfig------> daemonize()

initServer()-----> aeSetBeforeSleepProc()------>aeMain()----->

aeDeleteEventLoop

接下來詳細說一下每一個步驟都做了什麼。

看一下main()函數

int main(int argc, char **argv) {

    //設定時間,一般都是設定事件poll等待多長時間傳回

     struct timeval tv;

    /* We need to initialize our libraries, and the server configuration. */

    #ifdef INIT_SETPROCTITLE_REPLACEMENT

        //程序重命名

        spt_init(argc, argv);

    #endif

   //好像是更改字元編碼

    setlocale(LC_COLLATE,"");

    //設定多線程安全模式

    zmalloc_enable_thread_safeness();

    //注冊記憶體使用過量報錯的函數

    zmalloc_set_oom_handler(redisOutOfMemoryHandler);

    srand(time(NULL)^getpid());

    gettimeofday(&tv,NULL);

    //哈希種子

    dictSetHashFunctionSeed(tv.tv_sec^tv.tv_usec^getpid());

    //伺服器的啟動模式:單機模式、Cluster模式、sentinel模式

    server.sentinel_mode = checkForSentinelMode(argc,argv);

    initServerConfig();

    loadServerConfig(configfile,options);

    。。。

           //建立守護程序

            if (server.daemonize) daemonize();

            //初始化伺服器

            initServer();

            //設定伺服器sleep之前的函數調用

            aeSetBeforeSleepProc(server.el,beforeSleep);

            //主函數事件驅動

            aeMain(server.el);

            //删除事件循環的結構,釋放空間

            aeDeleteEventLoop(server.el);

            return 0;

}

繼續閱讀