redis BIO詳解

BIO即background I/O service,後臺I/O服務,是redis的aof持久化後臺服務。

 

redis把阻塞的同步I/O操做交給後臺I/O服務來完成:close和fsync。

 

close加入BIO的緣由
1.若是fd是特定文件描述符的最後一份拷貝,那麼文件描述符相關的資源會被釋放。
2.若是fd是最後一個引用文件描述符的,而且文件描述符以前已經使用unlink進行刪除,那麼文件會被刪除。
資源釋放和文件刪除是很是慢的,會阻塞服務器

 

fsync加入BIO的緣由
把內存中修改的文件數據同步到磁盤。調用者將被阻塞至磁盤報告同步完成。

 

BIO的設計
目前有兩種任務:fsync和close。每種任務一個隊列和一個線程。

 

// 存放工做的隊列
static list *bio_jobs[REDIS_BIO_NUM_OPS];

 

// 記錄每種類型 job 隊列裏有多少 job 等待執行
static unsigned long long bio_pending[REDIS_BIO_NUM_OPS];

 

//初始化後臺服務,啓動後臺線程
void bioInit(void)

 

//建立後臺任務
void bioCreateBackgroundJob(int type, void *arg1, void *arg2, void *arg3) 

 

//處理後臺任務,後臺線程啓動函數
void *bioProcessBackgroundJobs(void *arg)
{
    //當任務數爲0的時候,調用pthread_cond_wait等待通知
    //任務數不爲0的時候,從隊列取任務並處理
         // 執行任務,type即線程啓動的入參,每一個後臺線程處理一種任務
        if (type == REDIS_BIO_CLOSE_FILE) {
            close((long)job->arg1);
        } else if (type == REDIS_BIO_AOF_FSYNC) {
            aof_fsync((long)job->arg1);
        } else {
            redisPanic("Wrong job type in bioProcessBackgroundJobs().");
        }
}

 

BIO的結構

 

 

BIO技術應用和優化
aof有三種持久化方案
1。內核同步,交給內核去緩存的數據到磁盤,大約30s一次。
2.每秒同步,這是做者推薦的同步方案,和內核同步幾乎同樣快。
3.每次都同步,性能極差,做者都巴不得刪掉這個功能。

 

fsync放在單獨線程處理存在的問題
fsync線程的使用和主線程的write存在衝突,在fsync進行的時候,write將被阻塞,fsync期間write不能執行,直到fsync完成。
redis中實現了一種優化

 

部分代碼
void flushAppendOnlyFile(int force) {
    // 策略爲每秒 FSYNC 
    if (server.aof_fsync == AOF_FSYNC_EVERYSEC)
        // 是否有 SYNC 正在後臺進行?
        sync_in_progress = bioPendingJobsOfType(REDIS_BIO_AOF_FSYNC) != 0;
    // 每秒 fsync ,而且強制寫入爲假
    if (server.aof_fsync == AOF_FSYNC_EVERYSEC && !force) {
         * 若是後臺仍在執行 FSYNC ,那麼咱們能夠延遲寫操做一兩秒
         * (若是強制執行 write 的話,服務器主線程將阻塞在 write 上面)
         */
        if (sync_in_progress) {
            // 有 fsync 正在後臺進行 。。。
             * 若是後臺還有 fsync 在執行,而且 write 已經推遲 >= 2 秒
             * 那麼執行寫操做(write 將被阻塞)
             */
    //write寫入緩衝區
    nwritten = write(server.aof_fd,server.aof_buf,sdslen(server.aof_buf));
優化方案
當aof同步方式爲每秒同步時,主線程的write進行優化,若是執行write時fsync服務正在同步中,那麼推遲write的時間,最多推遲兩秒,若是等待兩秒後fsync仍在同步,執行強制write操做,主線程將阻塞等待write完成。

 

fsync服務線程和bgsave以及bgrewriteaof子進程的衝突
這時候不該該執行fsync
    if (server.aof_no_fsync_on_rewrite &&
        (server.aof_child_pid != -1 || server.rdb_child_pid != -1))
            return;

 

做者關於fsync服務線程的博客
相關文章
相關標籤/搜索