mongodb 3.0支援使用者自定義存儲引擎,使用者可配置使用mmapv1或者wiredtiger存儲引擎,本文主要介紹mongodb是如何使用wiredtiger資料庫作為底層的資料存儲層。目前還沒有讀過wiredtiger的源碼,本文的内容都是基于wiredtiger官方文檔,以及mongodb對wiredtiger封裝代碼,有問題請指出。
wiredtiger(簡稱wt)支援行存儲、列存儲以及lsm等3種存儲形式,mongodb使用時,隻是将其作為普通的kv存儲引擎來使用,mongodb的每個集合對應一個wt的table,table裡包含多個key-value pairs,以b樹形式存儲。
以下是一個典型的使用wt存儲引擎的資料目錄布局(配置了directoryperdb選項,啟用了journal)
wiredtiger*等檔案存儲wt的一些配置資訊。
local、journal、admin、products等每個目錄代表一個db,db裡包含集合資料及集合的索引資料,每個集合的資料對應一個wt的table(一個.wt字尾的檔案),集合的每項索引也對應一個wt的table。
journal目錄下存儲wt的write ahead log,當服務crash時,可通過log來恢複資料。
_mdb_catalog.wt裡存儲了所有集合的中繼資料,包括集合對應的wt table名字,集合的建立選項,集合的索引資訊等,wt存儲引擎初始化時,會從_mdb_catalog.wt裡讀取所有的集合資訊,并加載元資訊到記憶體。
集合名與wt table名的對應關系可以通過db.collection.stats()擷取
也可以直接dump出_mdb_catalog.wt裡的内容檢視,dump出的内容為bson格式,閱讀起來不是很友善。
sizestorer.wt裡存儲所有集合的容量資訊,如文檔數、文檔總大小等,當插入、删除、更新文檔時,這些資訊會先cache到記憶體,沒操作1000次會刷盤一次;mongod程序crash可能導緻sizestorer.wt裡的資料與實際資訊不比對,可通過validate()指令來重新掃描集合以訂正統計資訊。
wt官方提供了c、java、python api,mongodb使用c api來通路wt資料庫,主要包括3個核心的資料結構。
wt_connection代表一個到wt資料庫的連接配接,通常每個程序隻用建立一個連接配接,wt_connection的所有方法都是線程安全的。
wt_session代表一個資料庫操作的上下文,每個線程需建立獨立的session。
wt_cursor用于操作某個資料集(如某個table、file),可使用cursor來進行資料庫插入、查詢操作。
如下是使用wiredtiger c api的示例,展示了如何向wt資料庫裡插入資料,更多示例參考這裡。
上述示例包含如下步驟
wiredtiger_open()建立連接配接
conn->open_session建立session
session->create()建立access表,并指定key、value格式
session->open_cursor建立cursor,并插入key-value
通路結束後conn->close()關閉連接配接
mongodb使用wiredtiger作為存儲引擎時,直接使用其c api來存儲、查詢資料。
mongodb在wiredtigerkvengine構造的時候wiredtiger_open建立連接配接,在其析構時關閉連接配接,其指定的配置參數為:
配置項
含義說明
create
如果資料庫不存在則先建立
cache_size=xx
cache大小,使用mongod cachesizegb配置項的值
session_max=20000
最大session數量
eviction=(threads_max=4)
淘汰線程最大數量,用于将page從cache逐出
statistics=(fast)
統計資料采用fast模式
statistics_log=(wait=xx)
統計資料采集周期,使用mongod statisticslogdelaysecs配置項的值
file_manager=(close_idle_time=100000)
空閑檔案描述符回收時間
checkpoint=(wait=xx,log_size:2g)
開啟周期性checkpoint,采用mongod syncperiodsecs配置項的值
log=(enabled=true,archive=true...
啟用write ahead log,達到2g時觸發checkpoint
重點介紹下checkpoint和log2個配置項,其決定了資料持久化的安全級别;wiredtiger支援2種資料持久化級别,分别是checkpoint durability 和 commit-level durability。
wiredtiger支援對目前的資料集進行checkpoint,checkpoint代表目前資料集的一個快照(或鏡像),wiredtiger可配置周期性的進行checkpoint(或當log size達到一定門檻值是做checkpoint)。
比如wt配置了周期性checkpoint(沒開啟log),每5分鐘做一次checkpoint,在t1時刻做了一次checkpoint得到資料集c1,則在接下來的5分鐘内,如果服務crash,則wt隻能将資料恢複到t1時刻。
wiredtiger通過write ahead log來支援commit-level durability。
開啟write ahead log後,對wt資料庫的更新都會先寫log,log的刷盤政策(通過trasaction_sync配置項 或者 begion_transaction參數指定)決定了持久化的級别。
mongodb的使用的持久化級别配置為
checkpoint=(wait=60,log_size=2g)
log=(enabled=true,archive=true,path=journal,compressor=snappy)
begin_transcation("sync=true")
具體政策為
每60s做一次checkpoint
開啟write ahead log,當log size達到2gb時做checkpoint;并自動删除不需要的log檔案。
每次commit_transaction時,調用fsync持久化已經commit的log。
基于上述配置,mongodb可以保證服務crash時,所有已經commit的操作都能通過log恢複。
mongodb使用session pool來管理wt的session,isolation=snapshot指定隔離級别為snapshot。
建立資料集合的參數如下
如果集合不存在則先建立
memory_page_max=10m
page記憶體最大值
split_pct=90
page split百分比
checksum=on
開啟校驗
key_format=q,value_format=u
key為int64_t類型(recordid),value為wt_item
資料集合的key為int64_t類型的recordid,rerordid在集合内部唯一,value為二進制的bson格式。
建立索引集合的參數如下
type=file,internal_page_max=16k,leaf_page_max=16k
配置樹節點大小
key_format=u,value_format=u
key-value均為wt_item格式
索引集合的key、value均為二進制資料。
table建立好之後,就可以往table
比如,往某個集合插入一組元素
對應一個coll的資料集合,其對應的wt資料類似于
key
value
1
{_id: "apple", count: 100}
2
{_id: "peach", count: 200}
3
{_id; "grape", count: 300}
以及基于id的索引集合,其對應的wt資料類似于
"apple"
"peach"
"grape"
接下來如果在count上建索引,索引會存儲在新的wt table裡,資料類似于
300
200
100
mongodb使用wiredtiger存儲引擎時,其将wiredtiger作為一個kv資料庫來使用,mongodb的集合和索引都對應一個wiredtiger的table。并依賴于wiredtiger提供的checkpoint + write ahead log機制提供高資料可靠性。