初探MongoDB

一、什麼是MongoDB

1.1 基本介紹

  MongoDB 是由C++語言編寫的,是一個基於分佈式文件存儲的開源數據庫系統。在高負載的情況下,可以添加更多的節點,來保證服務器性能。MongoDB 將數據存儲爲一個文檔,數據結構由鍵值對組成。MongoDB 文檔使用BSON格式;字段值可以包含其他文檔,數組及文檔數組。

1.2 BSON

  BSON是一種類json的一種二進制形式的存儲格式,簡稱Binary JSON,它和JSON一樣,支持內嵌的文檔對象和數組對象,但是BSON有JSON沒有的一些數據類型,如Date和BinData類型。
  BSON可以做爲網絡數據交換的一種存儲形式,這個有點類似於Google的Protocol Buffer,但是BSON是一種schema-less的存儲形式,它的優點是靈活性高,但它的缺點是空間利用率不是很理想。
  BSON有三個特點:輕量性、可遍歷性、高效性。
  MongoDB使用了BSON這種結構來存儲數據和網絡數據交換。把這種格式轉化成一文檔這個概念,因爲BSON是schema-free的,所以在MongoDB中所對應的文檔也有這個特徵,這裏的一個Document也可以理解成關係數據庫中的一條記錄,只是這裏的Document的變化更豐富一些,如Document可以嵌套。
  MongoDB以BSON做爲其存儲結構的一種重要原因是其可遍歷性。

1.3 MongoDB關鍵特性

1、高性能
2、豐富的查詢語言
3、高可用性

副本集,自動故障轉移,數據冗餘

4、水平可擴展性
5、支持多種存儲引擎

MMAPv1存儲引擎:<3.2的默認存儲引擎
WirdeTiger存儲引擎:>=3.2的默認存儲引擎
In-Memory存儲引擎:Changed in version 3.2.6

1.4 默認庫

MongoDB有三個默認庫:admin、local、config。

admin:
從權限的角度來看,這是"root"數據庫。要是將一個用戶添加到這個數據庫,這個用戶自動繼承所有數據庫的權限。一些特定的服務器端命令也只能從這個數據庫運行,比如列出所有的數據庫或者關閉服務器。
local:
這個庫的數據永遠不會被複制,可以用來存儲限於本地單臺服務器的任意集合。
config:
當MongoDB用於分片設置時,config數據庫在內部使用,用於保存分片的相關信息。

二、MongoDB的存儲引擎

2.1 WirdeTiger

2.1.1 基本介紹

  3.2之後的默認存儲引擎,用於將數據持久化存儲到硬盤文件中,WiredTiger提供文檔級別的併發控制,檢查點,數據壓縮和本地數據加密等功能。對於生產環境,更多的CPU可以有效提升wireTiger的性能,因爲它是多線程的。wiredTiger不像MMAPV1引擎那樣儘可能的耗盡內存,它可以通過在配置文件中指定“cacheSizeGB”參數設定引擎使用的內存量,此內存用於緩存工作集數據(索引、namespace,未提交的write,query緩衝等)。

2.1.2 文檔級別的併發控制

  MongoDB在執行寫操作時,WiredTiger 在文檔級別進行併發控制,就是說,在同一時間,多個寫操作能夠修改同一個集合中的不同文檔;當多個寫操作修改同一個文檔時,必須以序列化方式執行;這意味着,如果該文檔正在被修改,其他寫操作必須等待,直到在該文檔上的寫操作完成之後,其他寫操作相互競爭,獲勝的寫操作在該文檔上執行修改操作。
  對於大多數讀寫操作,WiredTiger使用樂觀併發控制,只在Global,database和Collection級別上使用意向鎖,如果WiredTiger檢測到兩個操作發生衝突時,導致MongoDB將其中一個操作重新執行,這個過程是系統自動完成的。

2.1.3 檢查點

  在檢查點操作開始時,WiredTiger提供指定時間點的數據庫快照,該快照呈現的是內存中數據的一致性視圖。當向磁盤寫入數據時,WiredTiger將快照中的所有數據以一致性方式寫入到數據文件中。一旦檢查點創建成功,WiredTiger保證數據文件和內存數據是一致性的,因此,檢查點擔當的是還原點,檢查點操作能夠縮短MongoDB從Journal日誌文件還原數據的時間。
  當WiredTiger創建檢查點時,MongoDB將數據刷新到數據文件中,在默認情況下,WiredTiger創建檢查點的時間間隔是60s,或產生2GB的Journal文件。在WiredTiger創建新的檢查點期間,上一個檢查點仍然是有效的,這意味着,即使MongoDB在創建新的檢查點期間遭遇到錯誤而異常終止運行,只要重啓,MongoDB就能從上一個有效的檢查點開始還原數據。
  當MongoDB以原子方式更新WiredTiger的元數據表,使其引用新的檢查點時,表明新的檢查點創建成功,MongoDB將老的檢查點佔用的磁盤空間釋放。使用WiredTiger 存儲引擎,如果沒有記錄數據更新的日誌,MongoDB只能還原到上一個檢查點;如果要還原在上一個檢查點之後執行的修改操作,必須使用Jounal日誌文件。

2.1.4 預寫記錄日誌

  WiredTiger使用預寫日誌的機制,在數據更新時,先將數據更新寫入到日誌文件,然後在創建檢查點操作開始時,將日誌文件中記錄的操作,刷新到數據文件,就是說,通過預寫日誌和檢查點,將數據更新持久化到數據文件中,實現數據的一致性。WiredTiger 日誌文件會持久化記錄從上一次檢查點操作之後發生的所有數據更新,在MongoDB系統崩潰時,通過日誌文件能夠還原從上次檢查點操作之後發生的數據更新。

2.1.5 內存使用

  WiredTiger 利用系統內存資源緩存兩部分數據:

內部緩存(Internal Cache)
文件系統緩存(Filesystem Cache)

  從MongoDB3.2版本開始,WiredTiger內部緩存的使用量,默認值是:1GB 或 60% of RAM - 1GB,取兩值中的較大值;文件系統緩存的使用量不固定,MongoDB自動使用系統空閒的內存,這些內存不被WiredTiger緩存和其他進程使用,數據在文件系統緩存中是壓縮存儲的。
  WiredTiger壓縮存儲集合和索引,壓縮減少磁盤空間消耗,但是消耗額外的CPU執行數據壓縮和解壓縮的操作。
  默認情況下,WiredTiger使用塊壓縮算法來壓縮Collections,使用前綴壓縮算法來壓縮Indexes,Journal日誌文件也是壓縮存儲的。對於大多數工作負載,默認的壓縮設置能夠均衡數據存儲的效率和處理數據的需求,即壓縮和解壓的處理速度是非常高的。
  當從MongoDB中刪除文檔或集合後,MongoDB不會將磁盤空間釋放給OS,MongoDB在數據文件中維護Empty Records的列表。當重新插入數據後,MongoDB從Empty Records列表中分配存儲空間給新的Document,因此,不需要重新開闢空間。爲了更新有效的重用磁盤空間,必須重新整理數據碎片。
  WiredTiger使用compact 命令,移除集合\中數據和索引的碎片,並將unused的空間釋放,調用語法:

db.runCommand ( { compact: '<collection>' } )

  在執行compact命令時,MongoDB會對當前的database加鎖,阻塞其他操作。在compact命令執行完成之後,mongod會重建集合的所有索引。

2.2 In-Memory

2.2.1 基本介紹

  In-Memory存儲引擎將數據存儲在內存中,除了少量的元數據和診斷日誌,In-Memory存儲引擎不會維護任何存儲在硬盤上的數據,避免磁盤的IO操作,減少數據查詢的延遲。

2.2.2 文檔級別的併發

  In-Memory存儲引擎在執行寫操作時,使用文件級別的併發控制,就是說,在同一時間,多個寫操作能夠同時修改同一個集合中的不同文檔;當多個寫操作修改同一個文檔時,必須以序列化方式執行;這意味着,如果該文檔正在被修改,其他寫操作必須等待。

2.2.3 內存使用

  In-Mmeory 存儲引擎需要將Data,Index,Oplog等存儲到內存中,通過mongod參數: --inMemorySizeGB 設置佔用的內存數量,默認值是:50% of RAM-1GB。指定In-Memory 存儲引擎使用的內存數據量,單位是GB:

mongod --storageEngine inMemory --dbpath <path> --inMemorySizeGB <newSize>

2.2.4 持久化

  由於In-Memory 存儲引擎不會持久化存儲數據,只將數據存儲在內存中,讀寫操作直接在內存中完成,不會將數據寫入到磁盤文件中,因此,不需要單獨的日誌文件,不存在記錄日誌和等待數據持久化的問題,當MongoDB實例關機或系統異常終止時,所有存儲在內存中的數據都將會丟失。

2.2.5 oplog

  In-Memory 存儲引擎不會將數據更新寫入到磁盤,但是會記錄oplog,該oplog是存儲在內存中的集合,MongoDB通過Replication將Primary成員的oplog推送給同一副本集的其他成員。如果一個MongoDB實例是Replica Set的Primary成員,該實例使用In-Memory存儲引擎,通過Replication將oplog推送到其他成員,在其他成員中重做oplog中記錄的操作,這樣,就能將在Primary成員中執行的數據修改持久化存儲。

三、MongoDB的日誌

  數據是MongoDB的核心,MongoDB必須保證數據的安全,不能丟失,Journal 是順序寫入的日誌文件,用於記錄上一個檢查點之後發生的數據更新,能夠將數據庫從系統異常終止事件中還原到一個有效的狀態。MongoDB使用預寫日誌機制實現數據的持久化:WiredTiger 存儲引擎在執行寫操作時,先將數據更新寫入到Journal文件。Journal Files是存儲在硬盤的日誌文件,每個Journal File大約是100MB,存儲在–dbpath下的Journal子目錄中,在執行檢查點操作,將數據的更新同步到數據文件。
  每隔一定的時間間隔,WiredTiger 存儲引擎都會執行檢查點操作,將緩存的數據更新日誌同步到硬盤上的數據文件中(On-磁盤 Files),在默認情況下,MongoDB啓用日誌記錄,也可以顯式啓用,只需要在啓動mongod 時使用–journal 參數:

mongod --journal

3.1 使用Journal日誌文件還原的過程

  WiredTiger創建檢查點,能夠將MongoDB數據庫還原到上一個CheckPoint創建時的一致性狀態,如果MongoDB在上一個檢查點之後異常終止,必須使用Journal日誌文件,重做從上一個檢查點之後發生的數據更新操作,將數據還原到Journal記錄的一致性狀態,使用Journal日誌還原的過程是:

獲取上一個檢查點創建的標識值:從數據文件(Data Files)中查找上一個檢查點發生的標識值(Identifier);
根據標識值匹配日誌記錄:從Journal Files 中搜索日誌記錄(Record),查找匹配上一個檢查點的標識值的日誌記錄;
重做日誌記錄:重做從上一個檢查點之後,記錄在Journal Files中的所有日誌記錄;

3.2 緩存日誌

  MongoDB配置WiredTiger使用內存緩衝區來存儲Journal Records,所有沒有達到128KB的Journal Records都會被緩存在緩衝區中,直到大小超過128KB。在執行寫操作時,WiredTiger將Journal Records存儲在緩衝區中,如果MongoDB異常關機,存儲在內存中的Journal Records將丟失,這意味着,WiredTiger將丟失最大128KB的數據更新。

3.3 日誌文件

  關於Journal文件,MongoDB在 --dbpath 目錄下創建 journal子目錄,WiredTiger將Journal 文件存儲在該目錄下,每一個Journal文件大約是100M,命名格式是:WiredTigerLog.,sequence是一個左邊填充0的10位數字,從0000000001開始,依次遞增。
  對於WiredTiger存儲引擎,Journal 文件具有以下特性:

標識日誌記錄:Journal文件的每一個日誌記錄(Record)代表一個寫操作;每一個記錄都有一個ID,用於唯一標識該記錄;
壓縮Journal文件:WiredTiger會壓縮存儲在Journal文件中的數據;
Journal文件大小的上限:每一個Journal文件大小的上限大約是100MB,一旦文件超過該限制,WiredTiger創建一個新的Journal文件;
自動移除Journal文件:WiredTiger自動移除老的Journal文件,只維護從上一個檢查點還原時必需的Journal文件;
預先分配Journal文件:WiredTiger預先分配Journal文件;

3.4 在異常宕機後恢復數據

  在MongoDB實例異常宕機後,重啓mongod實例,MongoDB自動重做(redo)所有的Journal Files,在還原Journal Files期間,MongoDB數據庫是無法訪問的。

四、MongoDB相關參數

4.1 WiredTiger參數設置

mongod 
--storageEngine wiredTiger 
--dbpath <path> 
--journal --wiredTigerCacheSizeGB <value>
--wiredTigerJournalCompressor <compressor>
--wiredTigerCollectionBlockCompressor <compressor>
--wiredTigerIndexPrefixCompression <boolean>

4.2 In-Memory參數設置

mongod 
--storageEngine inMemory
--dbpath <path> 
--inMemorySizeGB <newSize>
--replSet <setname>
--oplogSize <value>

  jurnal就是一個預寫事務日誌,來確保數據的持久性,wiredTiger每隔60秒(默認)或者待寫入的數據達到2G時,MongoDB將對journal文件提交一個checkpoint(檢測點,將內存中的數據變更flush到磁盤中的數據文件中,並做一個標記點,表示此前的數據表示已經持久存儲在了數據文件中,此後的數據變更存在於內存和journal日誌)。對於write操作,首先被持久寫入journal,然後在內存中保存變更數據,條件滿足後提交一個新的檢測點,即檢測點之前的數據只是在journal中持久存儲,但並沒有在MongoDB的數據文件中持久化,延遲持久化可以提升磁盤效率,如果在提交checkpoint之前,MongoDB異常退出,此後再次啓動可以根據journal日誌恢復數據。journal日誌默認每個100毫秒同步磁盤一次,每100M數據生成一個新的journal文件,journal默認使用了snappy壓縮,檢測點創建後,此前的journal日誌即可清除。mongod可以禁用journal,這在一定程度上可以降低它帶來的開支;對於單點mongod,關閉journal可能會在異常關閉時丟失checkpoint之間的數據(那些尚未提交到磁盤數據文件的數據);對於replica set架構,持久性的保證稍高,但仍然不能保證絕對的安全(比如replica set中所有節點幾乎同時退出時)。

五、總結

  本文介紹了MongoDB的一些基本特性、存儲引擎以及日誌相關的內容;在以後的文章中會重點分析對MongoDB的特性進行分析。

本文參考文章:https://www.cnblogs.com/phpandmysql/p/7763420.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章