Ceph bluestore中的快取管理

2021-10-05 07:18:57 字數 4236 閱讀 9341

從15年3月接觸ceph分布式儲存系統,至今已經5年了;因為工作的需要,對ceph的主要模組進行了較深入的學習,也在ceph**層面做了些許改進,以滿足業務需要(我們主要使用m版本)。最近得閒,將過往的一些學習心得、改進以及優化思路記錄下了,希望能對後來者有所幫助。

這是第四篇:ceph bluestore中的快取管理

bluestore構建在裸盤上,在使用者空間,通過freelistmanager以及allocator來管理磁碟空間且通過direct-io訪問磁碟,所以它不能夠利用到系統的pagecache。為了提公升效能,bluestore在使用者態實現了基於2q和lru演算法的cache。

在繼續後文前,我們先來明確幾個主要的結構及其作用:

object: ceph實際上分布式物件儲存系統,通過object來表示儲存系統中的io物件,類似傳統檔案系統中的檔案,由資料(bufferlist)和元資料(onode)兩部分組成

collection:pg的記憶體表示,常駐記憶體,它是object物件的邏輯倉庫

bluestore_cnode_t:collection的元資料

onode: object的元資料,包含物件id以及指向物件資料邏輯位置的extentmap結構

bluestore_onode_t:onode的元資料,儲存在db中

cache:bluestore 快取物件,有lrucache和twoqcache兩種

onodespace:onode的快取管理物件,包含乙個cache物件以及乙個unordered_map型別的onode對映

buffer:object物件資料(bufferlist,offset,len)的快取表示

bufferspace:用於管理buffer,包含乙個buffer的map,角色類似onodespace

collection與bluestore_cnode_t, onode與bluestore_onode_t的關係類似於linux檔案系統中記憶體inode與磁碟inode的關係

下面的uml類圖展示了上述物件之間的關係:

osd啟動時,bluestore會建立多個cache例項,之後從db載入collection到記憶體中時,通過cid % shard_num模與cache關聯,所有的collection常駐記憶體,通過乙個map來管理;每個collection包含乙個cache指標,乙個元資料物件bluestore_cnode_t以及乙個onodespace型別的onode_map變數,這個變數包含與collection相同的cache例項以及乙個onode的unorderd_map物件(這個unorderd_map應該是用來加速查詢的,因為cache可能被多個collection共享,通過每個onodespace中的專屬結構來管理本collection的onode,可以提公升效率)。

ceph中的物件元資料(這裡說的元資料是指資料元資料,物件屬性通過objectmap來管理)通過onode來管理,包含物件的id以及乙個extentmap結構來表示物件的資料偏移及長度資訊,每個extent表示邏輯上連續的資料片段,通過來標識;由於一段邏輯資料在物理上可能不連續,可能對應多個物理儲存區bluestore_pextent_t, 為便於管理引入了blob,它是bluestore_pextent_t的集合(pextentvector),blob還是ceph中的資料共享單位,快照轉殖的時候,共享資料通過更新引用計數即可,不需要磁碟拷貝。

bluestore提供了lru cache 和 2q cache兩種快取機制,預設採用2q cache。lrucache,淘汰最近最少使用的item,採用list來實現,onode和buffer各占用乙個佇列;twoqcache,針對onode和buffer採用不同的處理方式,其中onode快取採用lru實現,而buffer將整個快取空間分為三部分,使用三個佇列,分別稱為hot,warm_in,warm_out來管理,新加入的資料加入到warm_in佇列,再次訪問的資料加入到hot佇列,warm_in中的冷資料向移到warm_out佇列,另外twoqcache充分利用區域性性原理,加入物件時會根據offset匹配前後的物件,將新物件加入到臨近物件的前面。下圖是lru和2q快取的乙個示例說明:

快取系統的基本操作包括crud四種,cache主要提供了:add(c),touch(u),rm(d),trim(d)四個方法,onodespace或者bufferspace提供了:add(c),rename(u),lookup(r),discard (u),remove(d)四個方法, 可以想到onodespace和bufferspace實現了一部分業務語義:

add方法:包括onode和buffer兩部分,就onode而言:lrucache和twoqcache採用相同的策略,如果物件已經在快取中,則直接返回,否則將onode加入到onodespace的onode_map中並插入到cache的onode佇列的頭部;對於buffer:lrucache採用與onode相同的策略,將物件插入到cache的buffer佇列的頭部,而twoqcache維護了三個佇列,根據熱度屬性將物件分別新增到hot,warm_in,warm_out佇列。

lookup方法:用來從onodespace的onode_map中查詢物件,如果找到則通過touch方法將物件提公升到cache的onode佇列的頭部,需要注意的是twoqcache中,只有hot佇列中的佇列才會提公升到cache的頭部。

rm方法:包括onode和buffer兩部分,就onode而已:lrucache和twoqcache採用相同的策略,將物件從佇列中刪除,將物件從onodespace的onode_map中刪除;對於buffer:lrucache採用與onode相同的策略,將物件從佇列中刪除,twoqcache則將物件從hot,warm_in,warm_out之一中移除。

trim方法:根據需要保留的onode_max以及buffer_max清理快取,包括onode和buffer兩部分,基本上就是簡單的將物件從佇列中移除,twoqcache對buffer的處理有些許不同:它根據各佇列的資料空間佔比(ratio)來計算每個佇列需要移除的物件。

rename方法:處理物件的重新命名操作。

discard方法:淘汰給定區間的快取物件。

下文從快取初始化,讀io和寫io三個方面來分析bluestore cache的使用。

快取的初始化

1)osd init初始化時 bluestore根據設定的shard_num, cache_type建立cache例項

2)bluestore mount時從db載入collection,通過cid與 shard_num取模關聯特定的cache例項,blustore通過乙個map來管理記憶體中的collection。

讀io快取使用

1)bluestore收到讀請求後,從cache中獲取物件的onode(包含extent資訊),並且將onode移到佇列的頭部

2)如果上述獲取的onode的extent中不全部包含所需要的資訊,則從db中載入缺失部分的extent

3)根據從cache中讀取快取資料,並將命中的資料移到佇列頭部

4)對於不在快取中的資料則從後端磁碟上讀取,如果啟用了bufferio,則將資料加入到快取佇列頭部(warm_in佇列)

寫io快取使用

1)bluestore收到寫請求後,從cache中獲取onode或者建立乙個onode, 並將onode插入佇列的頭部

2)如果上述獲取的onode的extent中不全部包含所需要的資訊,則從db中載入缺失部分的extent

3)如果啟用了bufferio,則將資料(如果io區間有重疊會先從磁碟讀取資料做合併)加入到快取佇列的頭部

4)(在執行io前)將快取元資料(onode,sharedblob)持久化到db中(這個過程中,extentmap可能需要分片,根據needs_reshard_begin/needs_reshard_end來決定需要reshard的區間)。

步驟3中有幾點需要注意:

資料快取是以blob單位進行的,

如果和之前的快取資料有部分重疊,會truncate掉front和tail,如果完全包含則先從cache中刪除掉

根據資料的熱度屬性將物件新增到不同的佇列中,新增的資料插入到warm_in佇列,如果與之前的資料有重疊,那麼加入哪個佇列與之前資料的熱度屬性相關

ceph bluestore相關配置

bluestore 分割槽 block.wal 用於bluestore的內部日誌或寫前日誌 ssd block.db 用於儲存bluestore的內部元資料,基於rocksdb實現,類似索引提高效能 ssd 根分割槽 1.乙個小的分割槽使用xfs進行格式化,幷包含osd的基本元資料。這個資料目錄包含...

Python中的descriptor中的一點疑問

在我的印象中,類中的函式是可以有兩種呼叫方式的,如下 class b def func self return 10 b b b.func b.func b 於是,在之前研究descriptor的時候,我就有了幾點困惑 我將 更換成了如下兩個版本 版本1 import time class lazy...

python中的dict Python中的dict

dict python內建了字典 dict的支援,dict全稱dictionary,在其他語言中也稱為map,使用鍵 值 key value 儲存,具有極快的查詢速度。d print dict get michael d michael add a element d adam 67 print d...