聊聊dmclock 算法

人們常常容易忽略一些不起眼但特別重要的事物。曾經跟同事聊Python,有人說一切皆對象,這也是一些OOP的廣告詞,但我始終覺得一切皆函數。至今為止,還尚未聽過見過沒有函數的編程語言(SQL算不算?)。

很多QoS算法都不提隊列,但隊列是這類算法中最重要的要素了。具體來說,QoS算法的目的就是定義一個優先級隊列,定義隊列元素出隊列的先后順序。

從預留說起

起初把Reservation翻譯為下限,與上限(Limit)相對應,意為保證用戶IO不低于某個值。下限兩個字很容易誤解,如果用戶一段時間內不產生IO那實際IO為0又如何保證IO不低于某個值。它原本的含義是在系統繁忙的情況下,如果用戶產生的IO高于該值,保證實際IO不低于該值;如果用戶不產生IO或者產生的IO低于該值,那自然不用保證。

一次偶然機會看到有人將其翻譯成預留,頓時覺得妙,至少在用戶看來非常貼切。預留極易讓人聯想到生活中預訂餐桌的情況,假如預訂一個八人桌,那么餐館的服務生就會在其中一張八人桌上放個已被預訂的牌子以防止被其他顧客占用。預訂張八人桌能夠保證8個以內的人均有位置,但不保證第九個人也有位置,可能有也可能沒有。回到存儲,與預訂餐桌略有區別的是,預留并不會讓系統為用戶騰出一部分IO處理能力而等著用戶IO到來。

如何預留?
假設存儲系統有兩個用戶,兩個用戶都預留了10個IOPS,并且系統IO能力超過了兩個用戶的預留之和。

為保證用戶的預留,系統處理IO分兩個階段:第一階段先滿足每個用戶的預留,第二階段再將剩余能力分配給所有用戶。第一階段要解決的問題是如何判斷預留已滿足。對此,不同算法有不同的策略,最直觀的當屬令牌桶算法。算法每隔1/10秒就為兩個用戶各生成一張令牌,用戶的請求只有拿到令牌后才允許出隊列,當用戶無令牌可用時就說明該用戶已經達到預留,當所有用戶都無令牌可用時代表第一階段結束。令牌桶通過產生令牌的速度來模擬用戶預留的IO平均處理速度。

mClock的策略是依據IOPS將請求映射到時間軸,確定每個請求應該被處理的時刻。請求出隊列時只要將排在當前時刻前面的請求處理完就能夠滿足預留要求了

如何確定請求應該被處理的時刻?
依據IOPS的定義,每隔1/10秒處理一個請求,也就是說,時間軸上相鄰兩個請求的平均間隔為1/10秒。將系統接收到給定用戶的第一個請求放到時間軸中接收到該請求的時刻所在的位置,后續請求從前個請求的位置開始向右偏移1/10秒。假設系統在t1時刻開始接收請求,t2時刻開始處理請求,t1、t2的間隔恰好1秒。如果這段時間內系統剛好接收到10個請求,那么t2時刻處理完這10個請求就剛好滿足預留;如果這段時間內接收到的請求數目超過10個,那么超過的部分將排到t2后面,t2時刻只要處理掉它前面的請求就能夠滿足預留要求了。

所謂將請求擺到時間軸,具體到實現層面就是為請求添加一個Tag,Tag的內容為請求應該被處理的時刻。后文將預留的Tag,稱為R Tag。

考慮這樣一種應用場景,用戶起初有部分IO(時間段I),空閑了10分鐘(時間段II)后,又有了IO(時間段III)。根據上文描述的方法,時間段III中請求的R Tag將嚴重滯后當前時間。這將導致時間段III中的某個時刻解決掉所有排在它前面的請求后用戶實際的IOPS超過預留。這對該用戶來說是件好事,但對其它用戶極不公平,甚至會因為無法分配到IO而餓死。

上面的公式就是解決這個問題的方法,空閑了段時間后的第1個新請求將重新被設置為接收到該請求的時刻。公式中i代表用戶,r代表請求,R代表Tag的值。

前文的關注點主要在單用戶如何保證預留,多用戶情況最容易導致的問題是IO分配不公平。如果系統總IO能力低于兩個用戶的預留之和,會不會出現用戶餓死的情況?因為兩個用戶的請求都映射到時間軸,出隊列時按照時間從小到大的順序執行,因此不會出現不公平的問題。

上限有何不同

沒有。
預留過程可以分成兩步,第一步請求入隊列時為請求添加R Tag,第二步請求出隊列時決定哪些請求應該出隊列哪些請求不能出隊列。簡單來說,當前時刻前的請求出隊列,當前時刻后的請求不能出隊列。

上限也是如此兩步,只是含義略有不同。出隊列時,當前時刻前面的請求全部被處理掉代表此時IOPS已經達到用戶的上限,所以不能繼續處理當前時刻后面的請求,否則就超出上限了。

權重有何不同

有點。
上限和預留是針對給定用戶的絕對值,權重是用戶間的相對值。第二步只要根據P Tag從小到大的順序依次出隊列即可,即使P Tag超過了當前時間也可以繼續出隊列。

IOPS、帶寬和延遲

IOPS比較簡單,兩個請求之間沒有差別。帶寬稍微復雜點,要考慮到每個請求的大小。

假設某用戶的預留為10MB/s,可以理解為每秒鐘處理10MB數據,也可以理解為每1/10秒處理1個請求,每個請求的大小為1MB。為什么這么理解呢?因為我們需要找個參照物,此例以1MB的請求為參考,兩個相鄰的1MB大小的請求在時間軸上的間隔為1/10秒。那么,一個大小為512k的新請求與前一個請求的間隔應該設置為1/20;一個大小為2MB的請求和前個請求的間隔應該設置為1/5。

為什么比參照物小的請求間隔小,比參照物大的請求間隔大?這要從帶寬的定義來理解。

(待續)

突發IO

應用場景
大文件拷貝、虛擬機的啟動和遷移、數據庫批量更新、頁緩存刷新等。

不同廠商的定義
SolidFire定義突發IOPS能夠超過上限IOPS,只能持續一小段時間。HP 3PAR定義突發IO不能超過上限,只是通過抑制其它應用來提高突發應用的優先級。mClock對突發IO的定義和HP 3PAR相同,只是提高其比例不能越過上限。

(1)只在系統有余力的情況才允許突發IO;
(2)只調整P Tag,不影響預留和上限。

dmClock先檢查給定的應用是否空閑,如果空閑就給予一定的突發能力。

讀、寫和讀寫

(待續)

調度和調度引發的危機

(待續)

擴展mClock到多服務器

(待續)

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • 轉載自:https://xiaobailong24.me/2017/03/18/Android-RxJava2.x...
    Young1657閱讀 2,033評論 1 9
  • 摘要:在開發高并發系統時有三把利器用來保護系統:緩存、降級和限流。而有些場景并不能用緩存和降級來解決,因此需有一種...
    落羽成霜丶閱讀 2,168評論 0 18
  • AFHTTPRequestOperationManager 網絡傳輸協議UDP、TCP、Http、Socket、X...
    Carden閱讀 4,375評論 0 12
  • 昨晚,偶然聽到了這首《My prayer》,第一次知道這首歌是在一本叫《十年一品溫如言》的小說中,雖然這本小說的爭...
    請叫我花哥閱讀 415評論 0 0