原文地址 http://www.cnblogs.com/nbpowerboy/p/4325692.html
【摘要】當今已進入大資料時代,特別是大規模互連網web2.0應用不斷髮展及雲端運算所需要的海量儲存和海量計算髮展,傳統的關係型資料庫已無法滿足這方面的需求。隨著NoSQL資料庫的不斷髮展和成熟,可以較好地解決海量儲存和海量計算方面的應用需求。本文重點描述作為NoSQL之一MongoDB資料庫在海量資料存放區方面的應用。
1 引言
NoSQL,全稱是“Not Only Sql”,指的是非關係型的資料庫。這類資料庫主要有這些特點:非關係型的、分布式、開源的、水平可擴充的。原始目的是為了大規模web應用,這場全新的資料庫革命運動早期就有人提出,發展至2009年趨勢越發高漲。非關係型的資料存放區通常的應用如:模式自有、支援簡易複製、簡單的API、最終的一致性(非ACID)、大容量資料等。它的種類繁多,如列式資料庫(Hadoop/HBase、Cassandra、Hypertable、Amazon SimpleDB等)、文檔型資料庫(MongoDB、CouchDB、OrientDB等)、索引值資料庫(Azure Table Storage、MEMBASE、Redis、Berkeley DB、MemcacheDB等)、圖形資料庫(Neo4J、Infinite Graph、Sones、Bigdata等)、物件導向資料庫(db4o、Versant、Objectivity、Starcounter等)、網格及雲資料庫(GigaSpaces、Queplix、Hazelcast等)、XML資料庫(Mark Logic Server、EMC Documentum xDB、BaseX、Berkeley DB XML等)、多值資料庫(U2、OpenInsight、OpenQM等)及其他非關係型資料庫(如FileDB)等。
MongoDB屬於NoSQL資料的一種,是由10gen公司提供的一個開源的、模式自由的、面向文檔儲存的、分布式的資料庫,是一個介於關聯式資料庫和非關聯式資料庫之間的產品。由C++語言編寫,旨在為Web應用提供可擴充的高效能資料儲存解決方案。他支援的資料結構非常鬆散,是類似Json的Bson格式,因此可以儲存比較複雜的資料類型。
他可以運行在Solaris、Linux、Windows和OSX平台上,支援32位和64位應用,其中在32位應用中單個資料庫最大容量為2G,在64位應用中儲存容量大小隻與實際儲存空間大小有關,並且提供了Java、C#、PHP、C、C++、Javascript、Python、Ruby、Perl等多種語言的驅動程式,最新的生產版本為2.0,官方下載地址:http://www.mongodb.org/downloads。目前正在使用他的網站和企業已超過了100家,如視覺中國、福士點評網、淘寶網、盛大、Foursquare、Wordnik、OpenShift、SourceForge、Github等。
隨著企業資料不斷積累和增加及Web2.0應用不斷向前發展,已進入了個人資訊時代,對於大中型企業來說,可能每天將產生大量的資料,來之於各類系統,如各類文檔(OA文檔、項目文檔等)、設計圖紙、高清圖片、視頻等,對於員工來說,更關心的是個人資訊方面的儲存和計算,當這些資訊量足夠大時,想要即時提取或分析資料,傳統集中式方式難以滿足這方面的需求,因此採用分布式的儲存和計算成為必然的選擇,一方面主要解決海量儲存問題,另一方面解決海量計算問題。採用MongoDB的資料庫技術能有效地解決分布式方面的應用,本文重點分析MongoDB在海量資料存放區方面的應用。
2 概述
2.1 MongoDB的主要特點
(1)檔案儲存體格式為Bson,使用易於掌握和理解的Json風格文法。相對Json來說,Bson擁有更好的效能,主要表現為更快的遍曆速度、操作更簡易、增加了額外的
資料類型。
(2)模式自由,支援嵌入子文檔和數組,無需事先建立資料結構,屬於逆正常化的資料模型,有利於提高查詢速度。
(3)動態查詢,支援豐富的查詢運算式,使用Json形式的標記,可輕易查詢文檔中內嵌的對象和數組及子文檔。
(4)完整的索引支援,包括文檔內嵌對象和資料,同時還提供了全文索引方式,MongoDB的查詢最佳化工具會分析查詢運算式,並產生一個高效的查詢計劃。
(5)使用高效的位元據儲存,適合儲存大型物件(如高清圖片、視頻等)。
(6)支援多種複製模式,提供冗餘及自動容錯移轉。支援Master-Slave、Replica Pairs/Replica Sets、有限Master-Master模式。
(7)支援服務端指令碼和Map/Reduce,可以實現海量資料計算,即實現雲端運算功能。
(8)效能高、速度快。在多數場合,其查詢速度對於MySQL要快的多,對於CPU佔用非常小。部署很簡單,幾乎是零配置。
(9)自動處理片段,支援自動分區功能實現水平擴充的資料庫叢集,可以動態添加或移除節點。
(10)內建GridFS,支援海量儲存。
(11)可通過網路訪問,採用高效的MongoDB網路通訊協定,在效能方面要優於http或Rest協議。
(12)第三方支援豐富,MongoDB社區活躍,越來越多的公司和網站在生產環境中使用MongoDB進行技術架構最佳化,同時由10gen公司官方提供強大支援人員。
2.2 MongoDB的適用情境
MongoDB的主要目標是在鍵/值儲存方式(提供了高效能和高度伸縮性)以及傳統的RDBMS系統(豐富的功能)架起一座橋樑,集兩者的優勢於一身。
(1)網站資料:MongoDB非常適合即時的插入,更新與查詢,並具備網站即時資料儲存所需的複製及高度伸縮性。
(2)緩衝:由於效能很高,MongoDB也適合作為資訊基礎設施的緩衝層。在系統重啟之後,由MongoDB搭建的持久化緩衝層可以避免下層的資料來源過載。
(3)大尺寸,低價值的資料:使用傳統的關係型資料庫儲存一些資料時可能會比較昂貴,在此之前,很多時候程式員往往會選擇傳統的檔案進行儲存。
(4)高伸縮性的情境:MongoDB非常適合由數十或數百台伺服器組成的資料庫。MongoDB的路線圖中已經包含對MapReduce
引擎的內建支援。
(5)用於對象及JSON資料的儲存:MongoDB的Bson資料格式非常適合文檔化格式的儲存及查詢。
2.3 MongoDB的體繫結構
MongoDB是由一系列物理檔案(資料檔案,記錄檔等)的集合與之對應的邏輯結構(集合、文檔等)構成的資料庫。
MongoDB的邏輯結構實際是一種階層,由文檔(document,相當於關聯式資料庫中的row)、集合(collection,相當於關聯式資料庫中的table)、資料庫(database,相當於關聯式資料庫中的database)這三部分組成。
一個MongoDB執行個體支援多個資料庫。在MongoDB內部,每個資料庫都包含一個.ns檔案和一些資料檔案,採用預分配空間的機制,始終保持額外的空間和空餘的資料檔案,從而有效避免了由於資料暴增帶來的磁碟壓力過大問題。每個預分配的檔案都用0進行填充,資料檔案每新分配一次,他的大小都會是上一個資料檔案大小的2倍,每個資料檔案最大為2G。
2.4 MongoDB與MS SQL Server的語句對照
MongoDB提供了功能豐富的查詢運算式,可以實現絕大多數關聯式資料庫的sql語句功能,以表employee(id,name,age)舉例對照說明,如下圖1所示。
圖1 MongoDB與MS SQL Server語句對照
3 過程分析與測試
3.1 GridFS概述
由於MongoDB中的Bson對象大小是有限制的,在1.7版本以前單個Bson對象最大容量為4M,1.7版本以後單個Bson對象最大容量為16M[5]。對於一般的檔案儲存體,單個對象的4到16M的儲存容量能夠滿足需求,但無法滿足對於一些大檔案的儲存,如高清圖片、設計圖紙、視頻等,因此在海量資料存放區方面,MongoDB提供了內建的Grid
FS,可以將一個大檔案分割成為多個較小的文檔,可以指定檔案分塊標準,對使用者是透明的。GridFS使用兩個資料結構來儲存資料:files(包含中繼資料對象)、chunks(包含其他一些相關資訊的二進位塊)。為了使多個GridFS命名為一個單一的資料庫,檔案和塊都有一個首碼,預設首碼為fs,使用者有權改變這個首碼。
GridFS對Java、C#、Perl、PHP、Python、Ruby等程式言語均支援,且提供了良好的API介面。
3.2 基於GridFS的海量資料存放區測試
本文主要採用MongoDB最新版2.0及官方提供的C#語言驅動進行測試,C#驅動下載地址:https://github.com/mongodb/Mongo-csharp-driver。
MongoDB在bin目錄下提供了一系列有用的工具,可以很方便的進行營運管理:
(1)bsondump:將Bson格式的檔案轉儲為Json格式的資料。
(2)mongo:用戶端命令列工具,支援js文法。
(3)mongod:資料庫服務端,每個執行個體啟動一個進程,可以fork為後台運行。
(4)mongodump:Database Backup工具。
(5)mongorestore:資料庫恢複工具。
(6)mongoexport:資料匯出工具。
(7)mongoimport:資料匯入工具。
(8)mongofiles:GridFS管理工具,可實現二進位檔案的存取。
(9)mongos:分區路由,如果使用了sharding功能,則應用程式串連的是mongos,而非mongod。
(10)mongosniff:這一工具的作用類似於tcpdump,不同的是他只監控MongoDB相關包請求,並且是以指定的可讀性的形式輸出。
(11)mongostat:即時效能監控工具。
同時有好幾個第三方提供的用戶端圖形工具,如MongoVUE、RockMongo、MongoHub等,方便管理和維護。
GridFS結合自動分區及自動複製技術,可以實現高效能的分散式資料庫叢集架構,從而進行海量資料存放區,如下圖2所示。
圖2 高效能的分散式資料庫叢集架構
MongoDB Sharding Cluster需要三種角色:
(1)Shard Server:即儲存實際資料的分區,每個Shard可以是一個mongod執行個體,也可以是一組mongod執行個體構成的Replica Set。
(2)Config Server:用來儲存所有shard節點的配置資訊、每個chunk的shard key範圍、chunk在各shard的分布情況、該叢集中所有DB和collection的sharding配置資訊。
(3)Route Process:這是一個前端路由,用戶端由此接入,然後詢問Config Servers需要到哪個shard上查詢或儲存記錄,再串連相應的shard進行操作,最後將結果返回給用戶端,而這一切對用戶端是透明的,用戶端不用關心所操作的記錄儲存在哪個shard上。
為了測試方便,下面在同一台物理機器上構建一個簡單的Sharding Cluster,如下圖3所示。
圖3 簡單的Sharding Cluster架構圖
配置測試環境如下:
類比2個Shard伺服器和1個Config伺服器,均運行在本機127.0.0.1上,只是連接埠不同:
(1)Shard Server1:127.0.0.1:27020。
(2)Shard Server2:127.0.0.1:27021。
(3)Config Server:127.0.0.1:27022。
(4)Route Process:127.0.0.1:27017。
啟動相關服務進程:
c:\mongodb 2.0.0\bin>mongod --shardsvr --dbpath "c:\mongodb 2.0.0\db" --port 27020
d:\mongodb 2.0.0\bin>mongod --shardsvr --dbpath "d:\mongodb 2.0.0\db" --port 27021
e:\mongodb 2.0.0\bin>mongod --configsvr --dbpath "e:\mongodb 2.0.0\db" --port 27022
e:\mongodb 2.0.0\bin>mongos --configdb 127.0.0.1:27022
配置Sharding:
(1)e:\mongodb 2.0.0\bin>mongo
(2)use admin
(3)db.runCommand( { addshard : "127.0.0.1:27020", allowLocal : 1,
maxSize:2 , minKey:1, maxKey:10 } )
(4)db.runCommand( { addshard : "127.0.0.1:27021", allowLocal : 1, minKey:100 } )
(5)config =connect("127.0.0.1:27022")
(6)config = config.getSisterDB("config")
(7)ecDocs=db.getSisterDB("ecDocs")
(8)db.runCommand({enablesharding:"ecDocs"})
(9)db.runCommand( { shardcollection : "ecDocs.filedocs.chunks", key : { files_id : 1 } } )
(10)db.runCommand( { shardcollection : "ecDocs.filedocs.files", key : { _id : 1 } } )
以上的ecDocs是指資料庫名,filedocs是指使用者自訂的GridFS的檔案集合名,系統預設檔案集合名為fs。
使用官方提供的C#驅動,需要在程式中引用MongoDB.Driver.dllMongoDB.Bson.dll,迴圈添加同一檔案到GridFS範例程式碼,如下圖4所示。
圖4 迴圈添加同一檔案到GridFS代碼
測試組態環境如下:
作業系統:WindowsXP專業版32位SP3。
處理器(CPU):英特爾Xeon(至強)W3503@2.40GHz。
記憶體:3567MB(DDR31333MHz/FLASH)。
硬碟:希捷ST3250318AS(250GB/7200轉/分)。
由於本機是32位作業系統,因此單個服務執行個體只支援GridFS的檔案容量大小為0.9G左右,由於採用了兩台Shard服務執行個體,可以支援儲存的檔案總容量大小為1.8G左右,如果是64位作業系統就沒有此限制。
本文主要測試GridFS採用迴圈插入大容量檔案的效能和分區容量大小,測試結果,如下圖5所示。
從圖5可以看出,第1到3步驟,只添加單個檔案時,Shard2並沒有產生分區資料,只有測試到步驟4連續添加100個相同檔案時Shard2才產生分區資料,並且添加三四百兆的單個檔案,只需11秒多就完成了操作,而即使通過檔案拷貝方式這麼大的檔案也至少需要二三十秒才能完成,可見MongoDB在大容量檔案儲存體方面擁有非常高的效能。
通過在用戶端的mongo工具輸入db.printShardingStatus()命令可以查看詳細分區情況,如下圖6所示。
從圖6可以看出,在shard1中分配了6個chunks,在shard2中分配了7個chunks,分區資料相對還是比較均勻的。
從以上的測試可以得知,採用GridFS可以儲存海量資料,並且可以通過廉價伺服器進行大規模資料庫叢集,非常容易向外延展部署,程式編碼也非常容易,因此能夠有效支援雲端儲存的應用,能夠滿足大規模資料存放區的應用需求。