Redis的appendfsync參數詳解


redis.conf中的appendfysnc是對redis性能有重要影響的參數之一。可取三種值:alwayseverysecno

設置為always時,會極大消弱Redis的性能,因為這種模式下每次write后都會調用fsyncLinux為調用fdatasync)。

如果設置為no,則write后不會有fsync調用,由操作系統自動調度刷磁盤,性能是最好的。

everysec為最多每秒調用一次fsync,這種模式性能並不是很糟糕,一般也不會產生毛刺,這歸功於Redis引入了BIO線程,所有fsync操作都異步交給了BIO線程。

 

另外,Redis在處理一條命令時,並不立即調用writeAOF文件,只是將數據寫入到AOF bufferserver.aof_buf)中。調用write和命令處理是分開的,Redis只在每次進入epoll_wait之前做write操作。

/* Write the append only file buffer on disk.

 *

 * Since we are required to write the AOF before replying to the client,

 * and the only way the client socket can get a write is entering when the

 * the event loop, we accumulate all the AOF writes in a memory

 * buffer and write it on disk using this function just before entering

 * the event loop again.

 *

 * About the 'force' argument:

 *

 * When the fsync policy is set to 'everysec' we may delay the flush if there

 * is still an fsync() going on in the background thread, since for instance

 * on Linux write(2) will be blocked by the background fsync anyway.

 * When this happens we remember that there is some aof buffer to be

 * flushed ASAP, and will try to do that in the serverCron() function.

 *

 * However if force is set to 1 we'll write regardless of the background

 * fsync. */

#define AOF_WRITE_LOG_ERROR_RATE 30 /* Seconds between errors logging. */

void flushAppendOnlyFile(int force) {

    // aofWrite調用write將AOF buffer寫入到AOF文件,處理了ENTR,其它沒什么

    ssize_t nwritten = aofWrite(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));

    。。。。。。

    /* Handle the AOF write error. */

    if (server.aof_fsync == AOF_FSYNC_ALWAYS) {

        /* We can't recover when the fsync policy is ALWAYS since the

         * reply for the client is already in the output buffers, and we

         * have the contract with the user that on acknowledged write data

         * is synced on disk. */

        serverLog(LL_WARNING,"Can't recover from AOF write error when the AOF fsync policy is 'always'. Exiting...");

        exit(1);

    } else {

        return; /* We'll try again on the next call... */

    } else {

        /* Successful write(2). If AOF was in error state, restore the

         * OK state and log the event. */

    }

    。。。。。。

    /* Perform the fsync if needed. */

    if (server.aof_fsync == AOF_FSYNC_ALWAYS) {

        // redis_fsync是一個宏,Linux實際為fdatasync,其它為fsync

        // 所以最好不要將redis.conf中的appendfsync設置為always,這極影響性能

        redis_fsync(server.aof_fd); /* Let's try to get this data on the disk */

    }

    else if ((server.aof_fsync == AOF_FSYNC_EVERYSEC && server.unixtime > server.aof_last_fsync)) {

        // 如果已在sync狀態,則不再重復

        // BIO線程會間隔設置sync_in_progress

        // if (server.aof_fsync == AOF_FSYNC_EVERYSEC)

        //     sync_in_progress = bioPendingJobsOfType(BIO_AOF_FSYNC) != 0;

        if (!sync_in_progress)

            // eversec性能並不那么糟糕,因為它:

            // 后台方式執行fsync

            // Redis並不是嚴格意義上的單線程,實際上它創建一組BIO線程,專門處理阻塞和慢操作

            // 這些操作就包括FSYNC,另外還有關閉文件和內存的free兩個操作。

            // 不像always,EVERYSEC模式並不立即調用fsync,

            // 而是將這個操作丟給了BIO線程異步執行,

            // BIO線程在進程啟動時被創建,兩者間通過bio_jobs和bio_pending兩個

            // 全局對象交互,其中主線程負責寫,BIO線程負責消費。

            aof_background_fsync(server.aof_fd);

        server.aof_last_fsync = server.unixtime;

    }

}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM