天天看點

MongoDB如何使用wiredTiger?

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機制提供高資料可靠性。