基本概念基本特徵 1 豐富的資料類型 2 容易擴充 3 豐富的功能 4 不犧牲速度 5 簡便的管理 應用情境 儲存模型 並發控制 記憶體管理 容災備份 1 備份 2 修複 MongoDB傳輸協議 MongoDB檔案內部結構 MongoDB資料同步 分區機制
1 基本概念、基本特徵
MongoDB是一種強大、靈活、可擴充的資料存放區方式。它擴充了關係型資料庫的眾多有用功能,如輔助索引、範圍查詢(range query)和排序。MongoDB的功能非常豐富,比如內建的對MapReduce式彙總的支援,以及對地理空間索引的支援。
MongoDB的資料模型對開發人員來說非常友好,配置選項對於管理員來說也很輕鬆,並且有驅動程式和資料庫shell提供的自然語言式的API。MongoDB會為你掃除障礙,讓你關注編程本身而不是為儲存資料煩惱。
MongoDB只支援對單行記錄的原子性修改,並不支援對多行資料的原子操作。 1.1 豐富的資料類型
MongoDB是面向文檔的資料庫,不是關係型資料庫。放棄關聯式模式的主要原因就是為了更加方便的擴充性,當然還有其他好處。
基本的思路就是將原來“行”(row)的概念換成更加靈活的“文檔”(document)模型。面向文檔的方式可以將文檔或者數組內嵌進來,所以用一條記錄就可以表示非常複雜的層次關係。
MongoDB沒有模式:文檔的鍵不會事先定義也不會固定不變。由於沒有模式需要更改,通常不需要遷移大量資料。不必將所以資料都放到一個模子裡面,應用程式層可以處理新增或者丟失的鍵。 1.2 容易擴充
MongoDB從最初設計的時候就考慮到了擴充的問題。它所採用的面向文檔的資料模型使其可以自動在多台伺服器之間分割資料。它還可以平衡叢集的資料和負載,自動重排文檔。要是需要更大的容量,只需在叢集中添加新機器,然後讓資料庫處理剩下的事。 1.3 豐富的功能
(1)索引
MongoDB支援通用輔助索引,能進行多種快速查詢,也提供唯一的、複合的和地理空間索引能力。
(2)儲存JavaScript
開發人員不必使用預存程序了,可以直接在服務端存取JavaScript的函數和值。
(3)彙總
MongoDB支援MapReduce和其他彙總工具
(4)固定集合
集合的大小是有上限的,這對某些類型和資料(比如日誌)特別有用。
(5)檔案儲存體
MongoDB支援用一種容易使用的協議儲存大型檔案和檔案的中繼資料。
有些關係型資料庫的常見功能MongoDB並不具備,比如聯結(join)和複雜的多行事務。這個架構上的考慮是為了提高哦擴充性,因為這兩個功能實在很難在一個分布式系統上實現。 1.4 不犧牲速度
MongoDB使用MongoDB傳輸協議作為與伺服器互動的主要方式(與之對應的協議需要更多的開銷,如HTTP/REST)。它對文檔進行動態填充,預分配資料檔案,用空間換取效能的穩定。預設的儲存引擎中使用了記憶體對應檔,將記憶體管理工作交給作業系統去處理。動態查詢最佳化工具會“記住”執行查詢最高效的方式。 1.5 簡便的管理
MongoDB盡量讓伺服器自治來簡化資料庫的管理。除了啟動資料庫伺服器外,疾呼沒有什麼必要的管理操作。如果主伺服器掛掉了,MongoDB會自動切換到備份伺服器上,並且將備份伺服器提升為活躍伺服器。在分布式環境下,叢集只需要知道有新增的節點,就會自動整合和配置新節點。 2 應用情境
MongoDB的主要目標是在鍵/值儲存方式(提供了高效能和高度伸縮性)以及傳統的RDBMS系統(豐富的功能)架起一座橋樑,集兩者的優勢於一身。mongo適用於以下情境:
(1)網站資料:mongo非常適合即時的插入,更新與查詢,並具備網站即時資料儲存所需的複製及高度伸縮性。
(2)緩衝:由於效能很高,mongo也適合作為資訊基礎設施的緩衝層。在系統重啟之後,由mongo搭建的持久化緩衝可以避免下層的資料來源過載。
(3)大尺寸、低價值的資料:使用傳統的關聯式資料庫儲存一些資料時可能會比較貴,在此之前,很多程式員往往會選擇傳統的檔案進行儲存。
(4)高伸縮性的情境:mongo非常適合由數十或者數百台伺服器組成的資料庫。
(5)用於對象及JSON資料的儲存:mongo的BSON資料格式非常適合文檔格式化的儲存及查詢。
不適合的情境:
(1)高度事物性的系統:例如銀行或會計系統。傳統的關係型資料庫目前還是更適用於需要大量原子性複雜事務的應用程式。
(2)傳統的商業智慧應用:針對特定問題的BI資料庫會對產生高度最佳化的查詢方式。對於此類應用,資料倉儲可能是更合適的選擇。
(3)需要SQL的問題。 3 儲存模型
MongoDB的文檔是個抽象概念。其具體的呈現形式取決於使用的驅動和程式設計語言。因為MongoDB中的通訊大量依賴於文檔,所以需要一種所有驅動、工具和進程都能共用的文檔表達方式,這中表達叫做Binary JSON(BSON)。
BSON是輕量的二進位格式,能將MongoDB的所有文檔表示為位元組字串。資料庫能理解BSON,存在磁碟上的文檔也是這種格式。
當驅動要插入文檔,或者將文檔作為查詢條件,驅動會將文檔轉換成BSON,然後再發往伺服器。同樣,返回到用戶端的文檔也是BSON格式的字串。驅動需要將這些資料解碼,變成原生文檔表示,最後返回給用戶端。
用BSON格式的三個主要目標。
(1)效率
BSON設計用來更有效地表示資料,佔用更少的空間。最差的情況下,BSON比JSON效率略低;最好的情況下(比如存放位元據或大數),BSON要更高效得多。
(2)可便利性
有些時候BSON犧牲了空間效率,換取更容易遍曆的格式。例如,在字串前面加入其長度,而不是在結尾處使用一個終結符。這對MongoDB內省文檔很有用。
(3)效能
最後BSON的編碼和解碼速度都很快。它用C風格的表現方式來表示類型,在大多數程式設計語言中都非常快。 4 並發控制
MongoDB不支援事務,也就沒有資料庫層級的悲觀鎖了。那麼我們的並發控制只能依賴樂觀鎖。
(1)悲觀鎖:假定會發生並發衝突,屏蔽一切可能違反資料完整性的操作。
(2)樂觀鎖:假設不會發生並發衝突,只在提交操作時檢查是否違反資料完整性,樂觀鎖不能解決髒讀和多讀的問題。 5 記憶體管理
MongoDB預設的儲存引擎是記憶體映射引擎。當伺服器啟動後,將所有資料檔案映射到記憶體。然後由作業系統來負責將緩衝資料寫入磁碟並將資料調入調出記憶體頁面。這樣的引擎有若干重要的特性。
(1)MongoDB管理記憶體的代碼非常精鍊,原因就是大部分工作推給了作業系統。
(2)MongoDB伺服器處理序的虛擬大小通常會非常大,超過整個資料集的大小。
(3)MongoDB不能控制資料寫入到磁碟的順序,也就是不能用預寫記錄檔提供單機的持久性。
(4)32位的MongoDB伺服器有個限制,每個mongod最多隻能處理2GB資料。這是因為所有資料必須能用32位地址訪問到。 6 容災備份 6.1 備份
(1)mongodump和mongorestore
mongodump是一種能在運行時備份的方法,它對啟動並執行MongoDB做查詢,然後將所有查到的文檔寫入磁碟。Mongodump使用普通的查詢機制,所以產生的備份不一定是伺服器資料的即時快照,同時還會對其他用戶端的效能產生不利的影響。除了mongodump,MongoDB還提供了從備份中恢複資料的工具mongorestore。
(2)fsync和鎖
雖然用mongodump和mongorestore 能不停機備份,但是卻失去了擷取即時資料視圖的能力。MongoDB的fsync命令能在MongoDB運行時複製資料目錄還不會損毀資料。fsync命令會強制服務器將所有緩衝區寫入磁碟。還可以選擇上鎖阻止對資料庫的進一步寫入,直到釋放鎖為止。
(3)從屬備份
雖然上面說的幾種方式在備份資料方面已經很靈活了,但是都不及在從伺服器上備份,因為不太在乎從屬伺服器的效能或是能不能讀寫,於是就能隨意選擇上面的3種備份方式:關停、轉儲和恢複工具或fsync命令。 6.2 修複
MongoDB內建的修複功能會試著修複損壞的資料檔案。修複所有資料庫最簡單的方式就是加上—repair:mongod –repair來啟動伺服器。修複資料庫的實際過程實際上非常簡單:將所有文檔匯出然後馬上匯入,忽略那些無效的文檔。完成以後,會重建立立索引。 7 MongoDB傳輸協議
驅動在TCP/IP協議的基礎上簡單封裝了MongoDB傳輸協議,用來與MongoDB互動。基本上就是一個簡單封裝的BSON資料。例如,插入訊息會有20位元組的頭部資料(包括告知伺服器執行插入操作的代碼,以及訊息長度)、要插入的集合名、要插入的BSON文檔列表。 8 MongoDB檔案內部結構
MongoDB在資料存放區上按命名空間來劃分,一個Collection是一個命名空間,一個索引也是一個命名空間。
同一個命名空間的資料被分成很多個Extent,Extent之間使用雙向鏈表串連。
在每一個Extent中,儲存了具體每一行的資料,這些資料也是通過雙向連結來串連的。
每一行資料存放區空間不僅包括資料佔用空間,還可能包含一部分附加空間,這使得在資料Update變大後可以不移動位置。
索引以BTree結構實現。 9 MongoDB資料同步
MongoDB採用Replica Sets模式的同步流程
本流程可簡要描述如下:
(1)紅色箭頭表示寫操作可以寫到Primary上。然後非同步同步到多個Secondary上。
(2)藍色箭頭表示讀操作可以從Primary或Secondary任意一個中讀取。
(3)各個Primary與Secondary之間一直保持心跳同步檢測,用於判斷Replica Sets的狀態。 10 分區機制
MongoDB的分區是指定一個分區key來進行,資料按範圍分成不同的chunk,每個chunk的大小有限制。
有多個分區節點儲存這些chunk,每個節點儲存一部分的chunk。
每一個分區節點都是一個Replica Sets,這樣保證資料的安全性。
當一個chunk超過其限制的最大體積時,會分裂成兩個小的chunk。
當chunk在分區節點中分布不均衡時,會引發chunk遷移操作。
前面講了分區的機制,下面是具體在分區時幾種節點的角色
用戶端訪問路由節點mongos來進行資料讀寫。
config伺服器儲存了兩個映射關係,一個是key值的區間對應哪一個chunk的映射關係,另一個是chunk存在哪一個分區節點的映射關係。
路由節點通過config伺服器擷取資料資訊,通過這些資訊,找到真正存放資料的分區節點進行對應操作。
路由節點還會在寫操作時判斷當前chunk是否超出限定大小。如果超出,就分列成兩個chunk。
對於按分區key進行的查詢和update操作來說,路由節點會查到具體的chunk然後再進行相關的工作。
對於不按分區key進行的查詢和update操作來說,mongos會對所有下屬節點發送請求然後再對返回結果進行合并。