WiredTiger存儲引擎之六:Cache分配規則與Page的淘汰機制

image

前言算法

WiredTiger存儲引擎系列文章將從邏輯正確、內容完整的角度全面介紹WiredTiger存儲引擎。本篇做爲WiredTiger存儲引擎介紹系列文章第六篇,也是本系列文章的最後一篇。segmentfault

前面的內容您能夠點擊下方標題進行閱讀:緩存

本篇包含如下內容:網絡

  • WiredTiger存儲引擎的Cache分配規則
  • 內存Page的淘汰機制

1.2 Cache的分配機制數據結構

WiredTiger啓動的時候會向操做系統申請一部份內存給本身使用,這部份內存咱們稱爲Internal Cache,若是主機上只運行MongoDB相關的服務進程,則剩下的內存能夠做爲文件系統的緩存(File System Cache)並由操做系統負責管理,以下圖所示:架構

image

圖:Cache的分配規則併發

MongoDB啓動時,首先從整個主機內存中切一大塊出來分給WiredTiger的Internal Cache,用於構建B-Tree中的各類page以及基於這些page的增刪改查等操做。app

從MongoDB3.4版本開始,默認的Internal Cache大小由下面的規則決定:比較50% of (RAM - 1 GB)和256MB的大小,取其中較大者。例如,假設主機內存爲10GB,則Internal Cache取值爲50% of (10GB - 1 GB),等於4.5GB;高併發

若是主機內存爲1.2GB,則Internal Cache取值爲256MB。工具

而後,會從主機內存再額外劃一小塊給MongoDB建立索引專用,默認最大值爲500MB,這個規則適用於全部索引的構建,包括多個索引同時構建時。

最後,會將主機剩餘的內存(排除其它進程的使用)做爲文件系統緩存,供MongoDB使用,這樣MongoDB可將壓縮的磁盤文件也緩存到內存中,從而減小磁盤I/O。

爲了節省磁盤空間,集合和索引在磁盤上的數據是被壓縮的,默認狀況下集合採起的是塊壓縮算法,索引採起的是前綴壓縮算法。所以,同一份數據在磁盤、文件系統緩存和Internal Cache三個位置的格式是不同的,以下描述:

  • 全部數據在File System Cache中的格式和在磁盤上的格式是一致的,將數據先加載到文件系統緩存,不但能夠減小磁盤I/O次數,還能減小內存的佔用;
  • 索引數據加載到WiredTiger的Internal Cache後,格式與磁盤上的格式不同,但仍能利用其前綴壓縮的特性(即去掉索引字段上重複的前綴)減小對內存的佔用;
  • 集合數據加載到WiredTiger的Internal Cache後,其數據必須解壓後才能被後續各類操做使用,所以格式與磁盤上和File System Cache都不同。

1.3 Page淘汰機制

當cache裏面的「髒頁」達到必定比例或cache使用量達到必定比例時就會觸發相應的evict page線程來將pages(包含乾淨的pages和髒pages)按必定的算法(LRU隊列)淘汰出去,以便騰挪出內存空間,保障後面新的插入或修改等操做。

觸發page eviction條件由以下幾種參數控制,以下表所示:

參數名稱 默認配置值 含義
eviction_target 80% 當Cache的使用量達到80%時觸發work thread淘汰page
eviction_trigger 90% 當Cache的使用量達到90%時觸發application thread和work thread淘汰page
eviction_dirty_target 5% 當「髒數據」所佔Cache比例達到5%時觸發work thread淘汰page
eviction_dirty_trigger 20% 當「髒數據」所佔Cache比例達到20%時觸發application thread和work thread淘汰page

第一種狀況:當cache的使用量佔比達到參數eviction_ target設定值時(默認爲80%),會觸發後臺線程執行page eviction;

若是使用量繼續增加達到eviction_trigger參數設定值時(默認爲90%),應用線程支撐的讀寫操做等請求將被阻塞,應用線程也參與到頁面的淘汰中,加速淘汰內存中pages。

第二種狀況:當cache裏面的「髒數據」達到參數eviction_dirty_target設定值時(默認爲5%),會觸發後臺線程執行page eviction;

若是「髒數據」繼續增加達到參數eviction_dirty_trigger設定值(默認爲20%),同時會觸發應用線程來執行page eviction。

還有一種特性狀況:當在page上不斷進行插入或更新時,若是頁上內容佔用內存空間的大小大於系統設定的最大值(memory_page_max),則會強制觸發page eviction動做。

先經過將此大的page拆分爲多個小的page,再經過reconcile將這些小的pages保存到磁盤上,一旦reconcile寫入磁盤完成,這些pages就能從cache中淘汰出去,從而爲後面更多的寫入操做騰出空間。

默認狀況下WiredTiger只使用一個後臺線程來完成page eviction,爲了提高eviction的性能,咱們能夠經過參數threads_min和threads_max來設定evict server啓動的後臺線程數。

經過設定合理值,加速頁面淘汰,避免淘汰不及時致使應用線程也被迫加入到淘汰任務中來,形成應用線程對其它正常請求操做的阻塞。

淘汰一個page時,會先鎖住這個page,再檢查這個page上是否有其它線程還在使用(判斷是否有hazard point指針指向它),若有則不會evict這個page。

image

專欄做者:郭遠威

資深大數據解決方案諮詢顧問與架構師,MongoDB中文社區委員,長沙分會主席,多年通訊行業大數據研發、規劃、諮詢經驗;《大數據存儲MongoDB實戰指南》做者;阿里云云計算ACP認證專家。

也許您還感興趣——

imageimageimageimage

相關文章
相關標籤/搜索