Redis異步化組件模型

摘要

Redis對客戶端的IO事件處理是由主線程串行執行的,除了IO事件以外,這個線程還負責過時鍵的處理、複製協調、集羣協調等等,這些除了IO事件以外的邏輯會被封裝成周期性的任務由主線程週期性的處理,對於一些沒有必要放在主線程的邏輯,由Redis封裝成異步任務交給異步線程來處理,這篇文章主要介紹Redis的異步化線程模型。數據結構

Redis線程體系

Redis能夠說是基於單線程模型的,由於對於客戶端的全部讀寫請求的處理,都由一個主線程串行地處理,所以多個客戶端同時對一個鍵進行寫操做不會有併發問題,可是除了客戶端讀寫請求以外還有一些比較耗時的操做,如持久化RDB文件,持久化AOF文件等等,這些操做不能放在主線程裏面處理,所以Redis會在適當的時候fork子進程來異步的處理這種任務。除了這些,Redis還有一組異步任務處理線程,用於處理不須要主線程同步處理的工做,整體上Redis的線程體系結構大體以下圖:併發

Redis線程體系結構異步

上圖中間藍色的部分表明主線程,最左邊虛線表明經過fork獲得的子進程,用來處理RDB持久化以及AOF持久化等任務,最右邊橙色部分表明一組異步任務處理線程,下面會詳細介紹這組異步任務處理線程,即Redis異步化組件——BIO組件。spa

Redis異步化組件模型

在Redis中,異步任務處理線程組被封裝在BIO組件中,源文件爲bio.h和bio.c。BIO組件目前包括三個線程,分別處理三種類型的任務:操作系統

  1. 文件句柄關閉任務
  2. AOF持久化任務
  3. 空間懶釋放

BIO內部的結構示意圖以下圖所示:線程

BIO異步任務處理組件結構server

任務類型

上面提到,Redis BIO組件提供的異步任務處理線程組目前只包含三個線程分別處理三類任務,這裏稍微詳細介紹着三類任務:對象

文件句柄關閉任務

文件句柄的釋放(close)對於操做系統來講是一個比較重的操做,在Redis中,當須要從新建立新的文件句柄,廢棄的文件句柄失效的時候,這個廢棄的文件句柄將由異步任務處理線程來關閉。接口

AOF持久化任務

Redis對於AOF文件的持久化有三種策略:隊列

  1. 關閉AOF功能
  2. aof_fsync_everysec策略,即每秒一次,實際上並非必定一秒鐘一次
  3. aof_fsync_always策略,即每次IO事件處理完畢,都將AOF持久化

這三種策略分別對應不一樣的業務場景和用戶需求,默認的策略爲aof_fsync_everysec,這個時候對於aof緩衝區內容持久化工做會交給異步任務處理線程來處理。

空間懶釋放

內存的釋放也是比較重的操做,這部分工做能夠交給異步任務處理線程來處理,Redis中經過一部任務釋放的空間主要包括三種:

  1. 對象空間的釋放,噹噹前內存夠用的時候,主線程不會同步釋放廢棄對象的內存,交給異步任務處理線程來釋放,固然須要配合lazyfree_lazy_server_del參數使用。
  2. DB空間的異步釋放,當須要刪除DB的時候,Redis會申請一個新的哈希表做爲新的DB,將DB內存的釋放的工做交給異步任務處理線程來處理。
  3. slots-leys空間釋放,在Redis Cluster模式下,slots-keys是由Redis實現的跳躍表數據結構支撐的,當Redis Cluster須要刷新slots-keys的時候,首先建立一個新的跳躍表結構做爲新的slots-keys,而後將老的slots-keys結構釋放的工做交給異步任務處理線程來處理。

異步任務處理模型

每一個線程都有一個虛擬阻塞隊列,之因此叫虛擬阻塞隊列主要有兩個緣由,一個緣由是這個隊列並非一個真實的隊列結構,隊列的底層數據結構由Redis實現的跳躍表支持,另外一個緣由是這個隊列的阻塞喚醒機制主要由Redis基於pthread庫提供的線程同步原語實現的,如pthread_cond_wait、pthread_cond_notify等。BIO外部經過BIO組件提供的接口將任務提交到阻塞隊列,內部線程對任務進行處理,主線程、隊列以及異步任務處理線程協做流程圖以下如所示:

異步任務處理流程

阻塞等待處理模型

目前,Redis對於異步任務的提交都是異步的,主線程將任務提交到任務隊列同時喚醒阻塞的異步任務處理線程來隊列那任務進行處理,這個時候主線程不須要知道異步任務處理的狀況,Redis BIO組件也提供了阻塞等待的接口,當外部線程將任務提交到任務隊列以後能夠調用該接口進行同步等待,可是值得注意的是,這裏等待的只是正在執行的任務處理完畢的事件,而不必定是任務提交線程剛剛提交的任務處理完畢事件。目前Redis BIO提供了該接口,可是該接口並無被用到,若是加上這個邏輯,則上圖補充完畢以下:

加上同步等待的異步任務處理流程

 

總結

Redis的單線程模型串行的處理客戶端請求以及一些其餘的事情,爲了提升單線程的應用效率,Redis將一些能夠異步處理的任務交給BIO組件提供的異步任務處理線程組來處理,這樣的好處是下降了主線程的壓力,分擔了主線程的部分工做量,可以讓主線程更快的響應客戶端的請求,在必定程度上提升了Redis的吞吐量。這種異步化模型在其餘應用場景也是很是有效的,我認爲其核心思想是:非核心邏輯異步化,提升主流程的處理效率。

相關文章
相關標籤/搜索