前言算法
WiredTiger存儲引擎系列文章將從邏輯正確、內容完整的角度全面介紹WiredTiger存儲引擎。本篇做爲WiredTiger存儲引擎介紹系列文章第六篇,也是本系列文章的最後一篇。segmentfault
前面的內容您能夠點擊下方標題進行閱讀:緩存
本篇包含如下內容:網絡
1.2 Cache的分配機制數據結構
WiredTiger啓動的時候會向操做系統申請一部份內存給本身使用,這部份內存咱們稱爲Internal Cache,若是主機上只運行MongoDB相關的服務進程,則剩下的內存能夠做爲文件系統的緩存(File System Cache)並由操做系統負責管理,以下圖所示:架構
圖: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三個位置的格式是不同的,以下描述:
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。
專欄做者:郭遠威
資深大數據解決方案諮詢顧問與架構師,MongoDB中文社區委員,長沙分會主席,多年通訊行業大數據研發、規劃、諮詢經驗;《大數據存儲MongoDB實戰指南》做者;阿里云云計算ACP認證專家。
也許您還感興趣——