淺談MongoDB內(nèi)部的存儲(chǔ)原理
存儲(chǔ)引擎
本文介紹默認(rèn)存儲(chǔ)引擎WiredTiger
WiredTiger架構(gòu)
WiredTiger的寫操作會(huì)先寫入Cache,并持久化到WAL(Write ahead log),每60s會(huì)做一次Checkpoint,將當(dāng)前的數(shù)據(jù)持久化,每,產(chǎn)生一個(gè)新的快照。Wiredtiger連接初始化時(shí),首先將數(shù)據(jù)恢復(fù)至最新的快照狀態(tài),然后根據(jù)Checkpoint恢復(fù)數(shù)據(jù),以保證存儲(chǔ)可靠性
btree與b+tree
雖然遍歷數(shù)據(jù)的查詢是相對(duì)常見的,但是 MongoDB 認(rèn)為查詢單個(gè)數(shù)據(jù)記錄遠(yuǎn)比遍歷數(shù)據(jù)更加常見,由于 B 樹的非葉結(jié)點(diǎn)也可以存儲(chǔ)數(shù)據(jù),所以 查詢一條數(shù)據(jù)所需要的平均隨機(jī) IO 次數(shù)會(huì)比 B+ 樹少,使用 B 樹的 MongoDB 在類似場(chǎng)景中的查詢速度就會(huì)比 MySQL 快。
這里并不是說 MongoDB 并不能對(duì)數(shù)據(jù)進(jìn)行遍歷,我們?cè)?MongoDB 中也可以使用范圍來查詢一批滿足對(duì)應(yīng)條件的記錄,只是需要的時(shí)間會(huì)比 MySQL 長(zhǎng)一些。MySQL 認(rèn)為遍歷數(shù)據(jù)的查詢是常見的,所以它選擇 B+ 樹作為底層數(shù)據(jù)結(jié)構(gòu)
cache
內(nèi)部緩存和文件系統(tǒng)緩存,默認(rèn)情況下內(nèi)部緩存取50%(RAM-1 GB)或256M較大者,文件系統(tǒng)緩存使用所有當(dāng)前可用的RAM。
Wiredtiger的Cache采用Btree的方式組織,每個(gè)Btree節(jié)點(diǎn)為一個(gè)page,root page是btree的根節(jié)點(diǎn),internal page是btree的中間索引節(jié)點(diǎn),leaf page是真正存儲(chǔ)數(shù)據(jù)的葉子節(jié)點(diǎn);btree的數(shù)據(jù)以page為單位按需從磁盤加載或?qū)懭氪疟P,btree的每個(gè)page以文件里的extent形式(由文件offset + size標(biāo)識(shí))存儲(chǔ)
page
ROW_ARRAY: 每個(gè)數(shù)組單元(wt_row)存儲(chǔ)的是這個(gè) kv row 在存儲(chǔ)在磁盤上的 page kv cell 行集合數(shù)據(jù)緩沖區(qū)偏移的位置和編碼方式(這個(gè)位置和編碼方式在 WT 上定義成一個(gè) wt_cell 對(duì)象),通過這個(gè)信息偏移位置信息就可以訪問到這一樣在緩沖區(qū)中的 K/V 內(nèi)容值 ROW_UPDATE_ARRAY: 一個(gè) mvcc list 對(duì)象,mvcc_list 與 wt_row 是一一對(duì)應(yīng)的,mvcc list 當(dāng)中存儲(chǔ)對(duì) wt_row 修改的值,修改的值包括值更新和值刪除,是一個(gè)無鎖單向鏈表
寫操作 遍歷btree,找到需要更新的page如果cache中沒有對(duì)應(yīng)的page,會(huì)從磁盤中加載page,鍵值對(duì)存入WT_ROW如果是insert操作,更新WT_INSERT,如果是update/delete操作,更新WT_UPDATE如果需要,將操作記錄寫入journal
我們通過一個(gè)實(shí)例來說明: 假如一個(gè) page 存儲(chǔ)了一個(gè) [0,100] 的 key 范圍,磁盤上原來存儲(chǔ)的行 key=2, 10 ,20, 30 , 50, 80, 90,他們的值分別是value = 102, 110, 120, 130, 150, 180, 190。 在 page 數(shù)據(jù)從磁盤讀到內(nèi)存后,分別對(duì) key=2 的 value 進(jìn)行了兩次修改,兩次修改的值是分別 402,502。對(duì) key = 20 ,50 的 value 做了一次修改,修改后的 value = 122, 155,后有分配 insert 了新的 key = 3,5, 41, 99,value = 203,205,241,299。 那么在內(nèi)存中的 page 就是如下圖組織數(shù)據(jù)的:
相鄰的兩 wt_row 之間可能不是連續(xù)的,他們之間可以插入新的單元,例如 row1(key = 2) 和 row2(key=10) 可以插入 3 和 5,這兩個(gè) row 之間需要有一個(gè)排序的數(shù)據(jù)結(jié)構(gòu)(WT用 skiplist 數(shù)據(jù)結(jié)構(gòu))來存儲(chǔ)插入的 K/V,就需要一個(gè) skiplist 對(duì)象數(shù)組 page_insert_array與row array對(duì)應(yīng)。這里需要說明的是 圖6 當(dāng)中紅色框當(dāng)中的 skiplist8,它是用于存儲(chǔ) row1(key=2) 范圍之前的 insert 數(shù)據(jù),圖中如果有 key =1 的數(shù)據(jù) insert,那么這個(gè)數(shù)據(jù)會(huì)新增到 skiplist8 當(dāng)中。
那么圖中row與 insert skiplist 的對(duì)應(yīng)關(guān)系就是:
row1 之前的范圍對(duì)應(yīng) insert 是 skiplist8row1 和 row2之間對(duì)應(yīng)的 insert 是 skiplist1row2 和 row3之間對(duì)應(yīng)的 insert 是 skiplist3…row7 之后的范圍對(duì)應(yīng)的 insert 是 skiplist7 checkpoint
一個(gè)Checkpoit包含如下元數(shù)據(jù): root page地址,地址由文件offset,size及內(nèi)容的checksum組成 alloc extent list地址,存儲(chǔ)從上次checkpoint起新分配的extent列表 discard extent list地址,存儲(chǔ)從上次checkpoint起丟棄的extent列表 available extent list地址,存儲(chǔ)可分配的extent列表,只有最新的checkpoint包含該列表 file size 如需恢復(fù)到該checkpoint的狀態(tài),將文件truncate到file size即可
WAL(journal)
日志文件記錄的是從上一個(gè)checkpoint之后的實(shí)際操作,該文件每100ms或文件大小到達(dá)100M就從緩存同步到磁盤
整體關(guān)系
分布式存儲(chǔ)
架構(gòu)
架構(gòu)圖:
寫數(shù)據(jù)流程:
讀數(shù)據(jù)流程:
到此這篇關(guān)于淺談MongoDB內(nèi)部的存儲(chǔ)原理的文章就介紹到這了,更多相關(guān)MongoDB存儲(chǔ)原理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MongoDB的$sample、aggregate和$rand實(shí)現(xiàn)隨機(jī)選取數(shù)據(jù)
在MongoDB中,我們可以使用內(nèi)置的$sample聚合操作符來隨機(jī)生成數(shù)據(jù),$sample可以從集合文檔中隨機(jī)選擇指定數(shù)量的文檔,但由于其查詢整個(gè)集合的性能問題,應(yīng)該慎用,aggregate方法以及$rand函數(shù)的結(jié)合使用可以實(shí)現(xiàn)更加靈活的查詢操作,并且可以對(duì)查詢結(jié)果進(jìn)行精細(xì)篩選2024-01-01centos6.5中安裝mongodb簡(jiǎn)明總結(jié)
這篇文章主要介紹了centos6.5中安裝mongodb簡(jiǎn)明總結(jié),本文簡(jiǎn)單的總結(jié)了安裝過程中的6個(gè)步驟,需要的朋友可以參考下2014-10-10PHP中安裝使用mongodb數(shù)據(jù)庫(kù)
最近有個(gè)項(xiàng)目,需要用php操作mongoDb數(shù)據(jù),所以了解下mongoDb為此整理了下,有需要的小伙伴可以參考下2015-12-12Windows下MongoDB配置用戶權(quán)限實(shí)例
這篇文章主要介紹了Windows下MongoDB配置用戶權(quán)限實(shí)例,本文實(shí)現(xiàn)需要輸入用戶名、密碼才可以訪問MongoDB數(shù)據(jù)庫(kù),需要的朋友可以參考下2015-01-01MongoDB實(shí)現(xiàn)查詢、分頁和排序操作以及游標(biāo)的使用
本文詳細(xì)講解了MongoDB實(shí)現(xiàn)查詢、分頁和排序操作以及游標(biāo)的使用方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07python實(shí)現(xiàn)爬蟲數(shù)據(jù)存到 MongoDB
本文給大家分享的是使用python實(shí)現(xiàn)將爬蟲爬到的數(shù)據(jù)存儲(chǔ)到mongoDB數(shù)據(jù)庫(kù)中的實(shí)例代碼,有需要的小伙伴可以參考下2016-09-09