WiredTiger存儲引擎之二:一個Page的生命週期(轉載)



 

本系列文章將從邏輯正確、內容完整的角度全面介紹WiredTiger存儲引擎。
本篇作爲WiredTiger存儲引擎介紹系列文章第二篇,包含如下內容:

  • Page的生命週期

  • Page的狀態

  • Page相關參數與調優

 

通過第一篇介紹,我們瞭解到數據以page爲單位加載到cache、cache裏面又會生成各種不同類型的page及爲不同類型的page分配不同大小的內存、eviction觸發機制和reconcile動作都發生在page上、page大小持續增加時會被分割成多個小page,所有這些操作都是圍繞一個page來完成的。
因此,有必要系統的分析一頁page的生命週期、狀態以及相關參數的配置,這對後續MongoDB的性能調優和故障問題的定位和解決有幫助。

Page的生命週期

 

 


Page的典型生命週期如下圖所示:

 

圖:page的生命週期

 

第一步:pages從磁盤讀到內存;

第二步:pages在內存中被修改;

第三步:被修改的髒pages在內存被reconcile,完成後將discard這些pages。

第四步:pages被選中,加入淘汰隊列,等待被evict線程淘汰出內存;

第五步:evict線程會將“乾淨“的pages直接從內存丟棄(因爲相對於磁盤page來說沒做任何修改),將經過reconcile處理後的磁盤映像寫到磁盤再丟棄“髒的”pages。

 

pages的狀態是在不斷變化的,因此,對於讀操作來說,它首先會檢查pages的狀態是否爲WT_REF_MEM,然後設置一個hazard指針指向要讀的pages,如果刷新後,pages的狀態仍爲WT_REF_MEM,讀操作才能繼續處理。
與此同時,evict線程想要淘汰pages時,它會先鎖住pages,即將pages的狀態設爲WT_REF_LOCKED,然後檢查pages上是否有讀操作設置的hazard指針,如有,說明還有線程正在讀這個page則停止evict,重新將page的狀態設置爲WT_REF_MEM;如果沒有,則pages被淘汰出去。

Page的各種狀態

 

 


針對一頁page的每一種狀態,詳細描述如下:
 WT_REF_DISK:初始狀態,page在磁盤上的狀態,必須被讀到內存後才能使用,當page被evict後,狀態也會被設置爲這個。
 WT_REF_DELETED:page在磁盤上,但是已經從內存B-Tree上刪除,當我們不在需要讀某個leaf page時,可以將其刪除。
 WT_REF_LIMBO:page的映像已經被加載到內存,但page上還有額外的修改數據在lookasidetable上沒有被加載到內存。
 WT_REF_LOOKASIDE:page在磁盤上,但是在lookasidetable也有與此page相關的修改內容,在page可讀之前,也需要加載這部分內容。
當對一個page進行reconcile時,如果系統中還有之前的讀操作正在訪問此page上修改的數據,則會將這些數據保存到lookasidetable;當page再被讀時,可以利用lookasidetable中的數據重新構建內存page。
 WT_REF_LOCKED:當page被evict時,會將page鎖住,其它線程不可訪問。
 WT_REF_MEM:page已經從磁盤讀到內存,並且能正常訪問。
 WT_REF_READING:page正在被某個線程從磁盤讀到內存,其它的讀線程等待它被讀完,不需要重複去讀。
 WT_REF_SPLIT:當page變得過大時,會被split,狀態設爲WT_REF_SPLIT,原來指向的page不再被使用。

Page的大小參數

 

 

 

 

無能將數據從磁盤讀到內存,還是從內存寫到磁盤,都是以page爲單位調度的,但是在磁盤上一個page到底多大?是否是最小分割單元?以及內存裏面的各種page的大小對存儲引擎的性能是否有影響?本節將圍繞這些問題,分析與page大小相關的參數是如何影響存儲引擎性能的。
總的來說,涉及到的關鍵參數和默認值如下表所示:

 

表:關鍵page參數和默認大小

參數名稱

默認配置值

含義

allocation_size

4KB

磁盤上最小分配單元

memory_page_max

5MB

內存中允許的最大page值

internal_page_max

4KB

磁盤上允許的最大internal  page值

leaf_page_max

32KB

磁盤上允許的最大leaf  page值

internal_key_max

1/10*internal_page

internal page上允許的最大key值

leaf_key_max

1/10*leaf_page

leaf page上允許的最大key值

leaf_key_value

1/2*leaf_page

leaf page上允許的最大value值

split_pct

75%

reconciled的page的分割百分比

 

詳細說明如下:

 

 allocation_size

MongoDB磁盤文件的最小分配單元(由WiredTiger自帶的塊管理模塊來分配),一個page的可以由一個或多個這樣的單元組成;默認值是4KB,與主機操作系統虛擬內存頁的大小相當,大多數場景下不需要修改這個值。

 memory_page_max

WiredTigerCache裏面一個內存page隨着不斷插入修改等操作,允許增長達到的最大值,默認值爲5MB。當一個內存page達到這個最大值時,將會被split成較小的內存pages且通過reconcile將這些pages寫到磁盤pages,一旦完成寫到磁盤,這些內存pages將從內存移除。
需要注意的是:split和reconcile這兩個動作都需要獲得page的排它鎖,導致應用程序在此page上的其它寫操作會等待,因此設置一個合理的最大值,對系統的性能也很關鍵。如果值太大,雖然spilt和reconcile發生的機率減少,但一旦發生這樣的動作,持有排它鎖的時間會較長,導致應用程序的插入或修改操作延遲增大;如果值太小,雖然單次持有排它鎖的時間會較短,但是會導致spilt和reconcile發生的機率增加。

 internal_page_max

磁盤上internalpage的最大值,默認爲4KB。隨着reconcile進行,internalpage超過這個值時,會被split成多個pages。
這個值的大小會影響磁盤上B-Tree的深度和internalpage上key的數量,如果太大,則internalpage上的key的數量會很多,通過遍歷定位到正確leaf page的時間會增加;如果太小,則B-Tree的深度會增加,也會影響定位到正確leaf page的時間。

 leaf_page_max

磁盤上leaf page的最大值,默認爲32KB。隨着reconcile進行,leaf page超過這個值時,會被split成多個pages。
這個值的大小會影響磁盤的I/O性能,因爲我們在從磁盤讀取數據時,總是期望一次I/O能多讀取一點數據,所以希望把這個參數調大;但是太大,又會造成讀寫放大,因爲讀出來的很多數據可能後續都用不上。

 internal_key_max

internalpage上允許的最大key值,默認大小爲internalpage初始值的1/10,如果超過這個值,將會額外存儲。導致讀取key時需要額外的磁盤I/O。

 leaf_key_max

leaf page上允許的最大key值,默認大小爲leaf page初始值的1/10,如果超過這個值,將會額外存儲。導致讀取key時需要額外的磁盤I/O。

 leaf_value_max

leaf page上允許的最大value值(保存真正的集合數據),默認大小爲leaf page初始值的1/2,如果超過這個值,將會額外存儲。導致讀取value時需要額外的磁盤I/O。

 split_pct

內存裏面將要被reconciled的 page大小與internal_page_max或leaf_page_max值的百分比,默認值爲75%,如果內存裏面被reconciled的page能夠裝進一個單獨的磁盤page上,則不會發生spilt,否則按照該百分比值*最大允許的page值分割新page的大小。

 

專欄作者:郭遠威

 



MongoDB中文社區委員,長沙分會主席

《大數據存儲MongoDB實戰指南》作者

資深大數據架構師,通信行業業務架構與數據遷移專家

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章