1. 程式人生 > >關於redis的單執行緒與後臺執行緒的原始碼分析

關於redis的單執行緒與後臺執行緒的原始碼分析

前言:

通常大家都會說redis是單執行緒的,這個理解其實也沒錯。

redis的命令處理基本上都是單執行緒處理的,除了個別任務會fork子程序進行處理。

分析版本:redis 3.0.7

其實redis是個多執行緒程序,如下圖:


redis的另外兩個執行緒的作用是什麼?

另外兩個執行緒用於一些非同步操作,通過條件變數控制任務,主要用於close(2),fsync(2)的操作,

因為close(2)一個檔案控制代碼時,如果程式是檔案的最後一個擁有者,那麼代表著要unlink它,相對來說會很慢,產生阻塞。

原始碼在哪裡?

src/bio.h

src/bio.c

/* Initialize the background system, spawning the thread. */
void bioInit(void) {
    pthread_attr_t attr;
    pthread_t thread;
    size_t stacksize;
    int j;

    /* Initialization of state vars and objects */
    for (j = 0; j < REDIS_BIO_NUM_OPS; j++) {
        pthread_mutex_init(&bio_mutex[j],NULL);
        pthread_cond_init(&bio_condvar[j],NULL);
        bio_jobs[j] = listCreate();
        bio_pending[j] = 0;
    }

    /* Set the stack size as by default it may be small in some system */
    pthread_attr_init(&attr);
    pthread_attr_getstacksize(&attr,&stacksize);
    if (!stacksize) stacksize = 1; /* The world is full of Solaris Fixes */
    while (stacksize < REDIS_THREAD_STACK_SIZE) stacksize *= 2;
    pthread_attr_setstacksize(&attr, stacksize);

    /* Ready to spawn our threads. We use the single argument the thread
     * function accepts in order to pass the job ID the thread is
     * responsible of. */
    for (j = 0; j < REDIS_BIO_NUM_OPS; j++) {
        void *arg = (void*)(unsigned long) j;
        if (pthread_create(&thread,&attr,bioProcessBackgroundJobs,arg) != 0) {
            redisLog(REDIS_WARNING,"Fatal: Can't initialize Background Jobs.");
            exit(1);
        }
        bio_threads[j] = thread;
    }
}


End;