1. 程式人生 > >MongoDB全面總結

MongoDB全面總結

原文地址:http://blog.csdn.net/jakenson/article/details/7060431

 MongoDB的內部構造《MongoDB The Definitive Guide》

MongoDB的官方文件基本是how to do的介紹,而關於how it worked卻少之又少,本人也剛買了《MongoDB TheDefinitive Guide》的影印版,還沒來得及看,本文原作者將其書中一些關於MongoDB內部現實方面的一些知識介紹如下,值得一看。

今天下載了《MongoDB The Definitive Guide》電子版,瀏覽了裡面的內容,還是挺豐富的。是官網文件實際應用方面的一個補充。和官方文件類似,介紹MongoDB的內部原理是少之又少,只有在附錄的一個章節中介紹了相關內容。

對於大多數的MongoDB的使用者來說,MongoDB就像是一個大黑盒,但是如果你能夠了解到MongoDB內部一些構造的話,將有利於你更好地理解和使用MongoDB。

BSON

在MongoDB中,文件是對資料的抽象,它被使用在Client端和Server端的互動中。所有的Client端(各種語言的Driver)都會使用這種抽象,它的表現形式就是我們常說的BSON(Binary JSON )。

BSON是一個輕量級的二進位制資料格式。MongoDB能夠使用BSON,並將BSON作為資料的儲存存放在磁碟中。

當Client端要將寫入文件,使用查詢等等操作時,需要將文件編碼為BSON格式,然後再發送給Server端。同樣,Server端的返回結果也是編碼為BSON格式再放回給Client端的。

使用BSON格式出於以下3種目的:

效率

BSON是為效率而設計的,它只需要使用很少的空間。即使在最壞的情況下,BSON格式也比JSON格式再最好的情況下儲存效率高。

傳輸性

在某些情況下,BSON會犧牲額外的空間讓資料的傳輸更加方便。比如,字串的傳輸的字首會標識字串的長度,而不是在字串的末尾打上結束的標記。這樣的傳輸形式有利於MongoDB修改傳輸的資料。

效能

最後,BSON格式的編碼和解碼都是非常快速的。它使用了C風格的資料表現形式,這樣在各種語言中都可以高效地使用。

寫入協議

Client端訪問Server端使用了輕量級的TCP/IP寫入協議。這種協議在

MongoDB Wiki中有詳細介紹,它其實是在BSON資料上面做了一層簡單的包裝。比如說,寫入資料的命令中包含了1個20位元組的訊息頭(由訊息的長度和寫入命令標識組成),需要寫入的Collection名稱和需要寫入的資料。

資料檔案

在MongoDB的資料資料夾中(預設路徑是/data/db)由構成資料庫的所有檔案。每一個數據庫都包含一個.ns檔案和一些資料檔案,其中資料檔案會隨著資料量的增加而變多。所以如果有一個數據庫名字叫做foo,那麼構成foo這個資料庫的檔案就會由foo.ns,foo.0,foo.1,foo.2等等組成。

資料檔案每新增一次,大小都會是上一個資料檔案的2倍,每個資料檔案最大2G。這樣的設計有利於防止資料量較小的資料庫浪費過多的空間,同時又能保證資料量較大的資料庫有相應的空間使用。

MongoDB會使用預分配方式來保證寫入效能的穩定(這種方式可以使用–noprealloc關閉)。預分配在後臺進行,並且每個預分配的檔案都用0進行填充。這會讓MongoDB始終保持額外的空間和空餘的資料檔案,從而避免了資料增長過快而帶來的分配磁碟空間引起的阻塞。

名字空間和盤區

每一個數據庫都由多個名字空間組成,每一個名字空間儲存了相應型別的資料。資料庫中的每一個Collection都有各自對應的名字空間,索引檔案同樣也有名字空間。所有名字空間的元資料都儲存在.ns檔案中。

名字空間中的資料在磁碟中分為多個區間,這個叫做盤區。在下圖中,foo這個資料庫包含3個數據檔案,第三個資料檔案屬於空的預分配檔案。頭兩個資料檔案被分為了相應的盤區對應不同的名字空間。

上圖顯示了名字空間和盤區的相關特點。每一個名字空間可以包含多個不同的盤區,這些盤區並不是連續的。與資料檔案的增長相同,每一個名字空間對應的盤區大小的也是隨著分配的次數不斷增長的。這樣做的目的是為了平衡名字空間浪費的空間與保持某一個名字空間中資料的連續性。上圖中還有一個需要注意的名字空間:$freelist,這個名字空間用於記錄不再使用的盤區(被刪除的Collection或索引)。每當名字空間需要分配新的盤區的時候,都會先檢視$freelist是否有大小合適的盤區可以使用。

記憶體對映儲存引擎

MongoDB目前支援的儲存引擎為記憶體對映引擎。當MongoDB啟動的時候,會將所有的資料檔案對映到記憶體中,然後作業系統會託管所有的磁碟操作。這種儲存引擎有以下幾種特點:

* MongoDB中關於記憶體管理的程式碼非常精簡,畢竟相關的工作已經有作業系統進行託管。

* MongoDB伺服器使用的虛擬記憶體將非常巨大,並將超過整個資料檔案的大小。不用擔心,作業系統會去處理這一切。

* MongoDB無法控制資料寫入磁碟的順序,這樣將導致MongoDB無法實現writeahead日誌的特性。所以,如果MongoDB希望提供一種durability的特性(這一特性可以參考我寫的關於Cassandra文章:http://www.cnblogs.com/gpcuster/tag/Cassandra/),需要實現另外一種儲存引擎。

* 32位系統的MongoDB伺服器每一個Mongod例項只能使用2G的資料檔案。這是由於地址指標只能支援32位。

其他

在《MongoDB The Definitive Guide》中介紹的MongoDB內部構造只有這麼多,如果真要把它說清楚,可能需要另外一本書來專門講述了。比如內部的JS解析,查詢的優化,索引的建立等等。有興趣的朋友可以直接參考原始碼

MongoDB的架構

當前架構                           雙伺服器架構


當前架構為單shard+replica Set模式,雙伺服器為雙Shard+Replica Set模式。同一個Shard中的primary和Secondary儲存內容一致。而雙Shard則是兩個Shard分散式儲存不同資料,備份由shard內部進行。

雙伺服器中的兩個Shard各含一個primary ,一個secondary,和一個arbiter(arbiter的唯一作用是在primary 宕機後選舉新的primary時擁有投票權,用以使存活節點數大於50%,不包括50%,否則系統將整個down掉,以及在票數相同的情況下用以打破選舉的平衡,並不儲存和讀取資料)。

因為同一個shard中,只有primary可以用以寫,secondary只是用於對primary節點的備份並用於讀操作,然後再primary宕機的情況下接管它的工作。所以,雙shard模式下,兩個伺服器分別包含一個primary,而且同一個shard的arbiter必須和secondary在一個伺服器上。這樣子既保證了兩個伺服器都可以進行讀、寫操作,而且在primary down的時候也能夠繼續使得選取成功secondary。

後續擴充套件時,可以再在叢集中新增新的shard,然後與老的shard進行balance均衡操作。

MongoDB的特點

MongoDB 是一個面向集合的,模式自由的文件型資料庫.

面向集合, 意思是資料被分組到若干集合,這些集合稱作聚集(collections). 在資料庫裡每個聚集有一個唯一的名字,可以包含無限個文件. 聚集是RDBMS中表的同義詞,區別是聚集不需要進行模式定義.

模式自由, 意思是資料庫並不需要知道你將存入到聚集中的文件的任何結構資訊.實際上,你可以在同一個聚集中儲存不同結構的文件.

文件型, 意思是我們儲存的資料是鍵-值對的集合,鍵是字串,值可以是資料型別集合裡的任意型別,包括陣列和文件. 我們把這個資料格式稱作 "[BSON]"即 "Binary Serialized dOcument Notation."

u  面向文件儲存:(類JSON資料模式簡單而強大)。

u  高效的傳統儲存方式:支援二進位制資料及大型物件(如照片和視訊)。

u  複製及自動故障轉移:Mongo資料庫支援伺服器之間的資料複製,支援主-從模式及伺服器之間的相互複製。

u  Auto-Sharding自動分片支援雲級擴充套件性(處於早期alpha階段):自動分片功能支援水平的資料庫叢集,可動態新增額外的機器。

u  動態查詢:它支援豐富的查詢表示式。查詢指令使用JSON形式的標記,可輕易查詢文件中內嵌的物件及陣列。

u  全索引支援:包括文件內嵌物件及陣列。Mongo的查詢優化器會分析查詢表示式,並生成一個高效的查詢計劃。

u  支援RUBY,PYTHON,JAVA,C++,PHP等多種語言。

u  面向集合儲存,易儲存物件型別的資料:儲存在集合中的文件,被儲存為鍵-值對的形式。鍵用於唯一標識一個文件,為字串型別,而值則可以是各中複雜的檔案型別;

u  *模式自由:儲存在mongodb資料庫中的檔案,我們不需要知道它的任何結構定義;

u  *支援完全索引,包含內部物件。

u  *支援複製和故障恢復。

u  *自動處理碎片: 自動分片功能支援水平的資料庫叢集,可動態新增額外的機器

u 查詢監視:Mongo包含一個監視工具用於分析資料庫操作的效能

MongoDB的功能

       查詢:基於查詢物件或者類SQL語句搜尋文件. 查詢結果可以排序,進行返回大小限制,可以跳過部分結果集,也可以返回文件的一部分.

       插入和更新 : 插入新文件,更新已有文件.

       索引管理 : 對文件的一個或者多個鍵(包括子結構)建立索引,刪除索引等等

常用命令: 所有MongoDB 操作都可以通過socket傳輸的DB命令來執行.

MongoDB的侷限性與不足

本文來源於對Quora上一個問答的整理,主要列舉了MongoDB身上一些侷限的功能及目前做得不夠好的地方。其中包括了原本就並非MongoDB想做的部分,也包括了MongoDB想做但沒做好的方面。

  • 在32位系統上,不支援大於2.5G的資料。詳見這裡
  • 單個文件大小限制為 4 M/16 M(1.8版本後升為16M)
  • 鎖粒度太粗,MongoDB使用的是一把全域性的讀寫鎖,詳見這裡
  • 不支援join操作和事務機制,這個確實是非MongoDB要做的領域
  • 對記憶體要求比較大,至少要保證熱資料(索引,資料及系統其它開銷)都能裝進記憶體
  • 使用者許可權方面比較弱,這一點MongoDB官方推薦的是將機器部署在安全的內網環境中,儘量不要用許可權,詳見這裡
  • MapReduce在單個例項上無法並行,只有採用Auto-Sharding才能並行。這是由JS引擎的限制造成的
  • MapReduce的結果無法寫入到一個被Sharding的Collection中,2.0版本對這個問題的解決好像也不徹底
  • 對於陣列型的資料操作不夠豐富
  • Auto-Sharding還存在很多問題,所謂的水平擴充套件也不是那麼理想

適用範圍

u  適合實時的插入,更新與查詢,並具備應用程式實時資料儲存所需的複製及高度伸縮性。

u  適合作為資訊基礎設施的持久化快取層。

u  適合由數十或數百臺伺服器組成的資料庫。因為Mongo已經包含對MapReduce引擎的內建支援。

u  Mongo的BSON資料格式非常適合文件化格式的儲存及查詢。

網站資料:Mongo非常適合實時的插入,更新與查詢,並具備網站實時資料儲存所需的複製及高度伸縮性。

u  ◆快取:由於效能很高,Mongo也適合作為資訊基礎設施的快取層。在系統重啟之後,由Mongo搭建的持久化快取層可以避免下層的資料來源過載。

u  ◆大尺寸,低價值的資料:使用傳統的關係型資料庫儲存一些資料時可能會比較昂貴,在此之前,很多時候程式設計師往往會選擇傳統的檔案進行儲存。

u  ◆高伸縮性的場景:Mongo非常適合由數十或數百臺伺服器組成的資料庫。Mongo的路線圖中已經包含對MapReduce引擎的內建支援。

u  ◆用於物件及JSON資料的儲存:Mongo的BSON資料格式非常適合文件化格式的儲存及查詢

MongoDB的不適用範圍

·        高度事務性的系統。

·        傳統的商業智慧應用。

·        級為複雜的SQL查詢。

·        ◆高度事務性的系統:例如銀行或會計系統。傳統的關係型資料庫目前還是更適用於需要大量原子性複雜事務的應用程式。

·        ◆傳統的商業智慧應用:針對特定問題的BI資料庫會對產生高度優化的查詢方式。對於此類應用,資料倉庫可能是更合適的選擇。

·        ◆需要SQL的問題

u   

要點

跟mysqld一樣,一個mongod服務可以有建立多個數據庫,每個資料庫可以有多張表,這裡的表名叫collection,每個collection可以存放多個文件(document),每個文件都以BSON(binary json)的形式存放於硬碟中。跟關係型資料庫不一樣的地方是,它是的以單文件為單位儲存的,你可以任意給一個或一批文件新增或刪除欄位,而不會對其它文件造成影響,這就是所謂的schema-free,這也是文件型資料庫最主要的優點。跟一般的key-value資料庫不一樣的是,它的value中儲存了結構資訊,所以你又可以像關係型資料庫那樣對某些域進行讀寫、統計等操作。可以說是兼備了key-value資料庫的方便高效與關係型資料庫的強大功能。

索引

跟關係型資料庫類似,mongodb可以對某個欄位建立索引,可以建立組合索引、唯一索引,也可以刪除索引。當然建立索引就意味著增加空間開銷,我的建議是,如果你能把一個文件作為一個物件的來考慮,在線上應用中,你通常只要對物件ID建立一個索引即可,根據ID取出物件某些資料放在memcache即可。如果是後臺的分析需要,響應要求不高,查詢非索引的欄位即便直接掃表也費不了太多時間。如果還受不了,就再建一個索引得了。

預設情況下每個表都會有一個唯一索引:_id,如果插入資料時沒有指定_id,服務會自動生成一個_id,為了充分利用已有索引,減少空間開銷,最好是自己指定一個unique的key為_id,通常用物件的ID比較合適,比如商品的ID。

capped collection是一種特殊的表,它的建表命令為:

db.createCollection("mycoll",{capped:true, size:100000})

允許在建表之初就指定一定的空間大小,接下來的插入操作會不斷地按順序APPEND資料在這個預分配好空間的檔案中,如果已經超出空間大小,則回到檔案頭覆蓋原來的資料繼續插入。這種結構保證了插入和查詢的高效性,它不允許刪除單個記錄,更新的也有限制:不能超過原有記錄的大小。這種表效率很高,它適用於一些暫時儲存資料的場合,比如網站中登入使用者的session資訊,又比如一些程式的監控日誌,都是屬於過了一定的時間就可以被覆蓋的資料。

複製與分片

mongodb的複製架構跟mysql也很類似,除了包括master-slave構型和master-master構型之外,還有一個Replica pairs構型,這種構型在平常可以像master-slave那樣工作,一但master出現問題,應用會自動了連線slave。要做複製也很簡單,我自己使用過master-slave構型,只要在某一個服務啟動時加上–master引數,而另一個服務加上–slave與–source引數,即可實現同步。

分片是個很頭疼的問題,資料量大了肯定要分片,mysql下的分片正是成為無數DBA的噩夢。在mongodb下,文件資料庫類似key-value資料庫那樣的易分佈特性就顯現出來了,無論構造分片服務,新增節點還是刪除節點都非常容易實現。但mongodb在這方面做還不足夠成熟,現在分片的工作還只做到alpha2版本(mongodb v1.1),估計還有很多問題要解決,所以只能期待,就不多說了。

效能

在我的使用場合下,千萬級別的文件物件,近10G的資料,對有索引的ID的查詢不會比mysql慢,而對非索引欄位的查詢,則是全面勝出。mysql實際無法勝任大資料量下任意欄位的查詢,而mongodb的查詢效能實在讓我驚訝。寫入效能同樣很令人滿意,同樣寫入百萬級別的資料,mongodb比我以前試用過的couchdb要快得多,基本10分鐘以下可以解決。補上一句,觀察過程中mongodb都遠算不上是CPU殺手。

gridfs是mongodb一個很有趣的類似檔案系統的東西,它可以用一大塊檔案空間來存放大量的小檔案,這個對於儲存web2.0網站中常見的大量小檔案(如大量的使用者頭像)特別有效。使用起來也很方便,基本上跟一般的檔案系統類似。

mongodb的文件裡提到的user case包括實時分析、logging、全文搜尋,國內也有人使用mongodb來儲存分析網站日誌,但我認為mongodb用來處理有一定規模的網站日誌其實並不合適,最主要的就是它佔空間過於虛高,原來1G的日誌資料它可以存成幾個G,如此下去,一個硬碟也存不了幾天的日誌。另一方面,資料量大了肯定要考慮sharding,而mongodb的sharding到現在為止仍不太成熟。由於日誌的不可更新性的,往往只需APPEND即可,又因為對日誌的操作往往只集中於一兩列,所以最合適作為日誌分析的還是列儲存型的資料庫,特別是像infobright那樣的為資料倉庫而設計的列儲存資料庫。

由於mongodb不支援事務操作,所以事務要求嚴格的系統(如果銀行系統)肯定不能用它。

一、主從配置(Master Slave)

    主從資料庫需要兩個資料庫節點即可,一主一從(並不一定非得兩臺獨立的伺服器,可使用--dbpath引數指定資料庫目錄)。一個從節點可以有多個主節點,這種情況下,local.sources中會有多條配置資訊。一臺伺服器可以同時即為主也為從。如果一臺從節點與主節點不同步,比如從節點的資料更新遠遠跟不上主節點或者從節點中斷之後重啟但主節點中相關的資料更新日誌卻不可用了。這種情況下,複製操作將會終止,需要管理者的介入,看是否預設需要重啟複製操作。管理者可以使用{resync:1} 命令重啟複製操作,可選命令列引數 --autoresync可使從節點在不同步情況發生10秒鐘之後,自動重啟複製操作。如果指定了--autoresync引數,從節點在10分鐘以內自動重新同步資料的操作只會執行一次。
--oplogSize命令列引數(與--master一同使用)配置用於儲存給從節點可用的更新資訊佔用的磁碟空間(M為單位),如果不指定這個引數,預設大小為當前可用磁碟空間的5%(64位機器最小值為1G,32位機器為50M)。

二、互為主從(Replica Pairs
資料庫自動協調某個時間點上的主從關係。開始的時候,資料庫會判斷哪個是從哪個是主,一旦主伺服器負載過高,另一臺就會自動成為主伺服器。
remoteserver組中的其他伺服器host,可加:port指定埠。
arbiterserver 仲裁(arbiter )的host,也可指定埠。仲裁是一臺mongodb伺服器,用於協助判斷某個時間點上的資料庫主從關係。如果同組伺服器在同一個交換機或相同的ec2可用區域內,就沒必要使用仲裁了。如果同組伺服器之間不能通訊,可是使用執行在第三方機器上的仲裁,使用“搶七”方式有效地敲定主伺服器,也可不使用仲裁,這樣所有的伺服器都假定是主伺服器狀態,可通過命令人工檢測當前哪臺資料庫是主資料庫:
$ ./mongo 
> db.$cmd.findOne({ismaster:1});
{ "ismaster" : 0.0 , "remote" : "192.168.58.1:30001" , "ok" : 1.0 } 
一致性:故障轉移機制只能夠保障組中的資料庫上的資料的最終一致性。如果機器L是主伺服器,然後掛了,那麼發生在它身上的最後幾秒鐘的操作資訊就到達不了機器R,那麼機器R在機器L恢復之前是不能執行這些操作的。
安全性:同主從的操作相同。
資料庫伺服器替換。當一臺伺服器失敗了,系統能自動線上恢復。但當一臺機器徹底掛了,就需要替換機器,而替換機器一開始是沒有資料的,怎麼辦?以下會解釋如何替換一組伺服器中的一臺機器。

MongoDB語法與現有關係型資料庫SQL語法比較

MongoDB語法                                  MySql語法

db.test.find({'name':'foobar'})<==> select * from test where name='foobar'

db.test.find()                            <==> select *from test

db.test.find({'ID':10}).count()<==> select count(*) from test where ID=10

db.test.find().skip(10).limit(20)<==> select * from test limit 10,20

db.test.find({'ID':{$in:[25,35,45]}})<==> select * from test where ID in (25,35,45)

db.test.find().sort({'ID':-1})  <==> select * from test order by IDdesc

db.test.distinct('name',{'ID':{$lt:20}})  <==> select distinct(name) from testwhere ID<20

db.test.group({key:{'name':true},cond:{'name':'foo'},reduce:function(obj,prev){prev.msum+=obj.marks;},initial:{msum:0}})  <==> select name,sum(marks) from testgroup by name

db.test.find('this.ID<20',{name:1})  <==> select name from test whereID<20

db.test.insert({'name':'foobar','age':25})<==>insertinto test ('name','age') values('foobar',25)

db.test.remove({})                        <==> delete * from test

db.test.remove({'age':20})            <==> delete test where age=20

db.test.remove({'age':{$lt:20}})   <==> elete test where age<20

db.test.remove({'age':{$lte:20}})  <==> delete test where age<=20

db.test.remove({'age':{$gt:20}})  <==> delete test where age>20

db.test.remove({'age':{$gte:20}})<==> delete test where age>=20

db.test.remove({'age':{$ne:20}})  <==> delete test where age!=20

db.test.update({'name':'foobar'},{$set:{'age':36}})<==> update test set age=36 where name='foobar'

db.test.update({'name':'foobar'},{$inc:{'age':3}})<==> update test set age=age+3 where name='foobar'

進行了一下Mongodb億級資料量的效能測試,分別測試如下幾個專案:
(所有插入都是單執行緒進行,所有讀取都是多執行緒進行)
1) 普通插入效能 (插入的資料每條大約在1KB左右)
2) 批量插入效能 (使用的是官方C#客戶端的InsertBatch),這個測的是批量插入效能能有多少提高
3) 安全插入功能 (確保插入成功,使用的是SafeMode.True開關),這個測的是安全插入效能會差多少
4) 查詢一個索引後的數字列,返回10條記錄(也就是10KB)的效能,這個測的是索引查詢的效能
5) 查詢兩個索引後的數字列,返回10條記錄(每條記錄只返回20位元組左右的2個小欄位)的效能,這個測的是返回小資料量以及多一個查詢條件對效能的影響
6) 查詢一個索引後的數字列,按照另一個索引的日期欄位排序(索引建立的時候是倒序,排序也是倒序),並且Skip100條記錄後返回10條記錄的效能,這個測的是Skip和Order對效能的影響
7) 查詢100條記錄(也就是100KB)的效能(沒有排序,沒有條件),這個測的是大資料量的查詢結果對效能的影響
8) 統計隨著測試的進行,總磁碟佔用,索引磁碟佔用以及資料磁碟佔用的數量

MongoDB CEO:NoSQL的大資料量處理能力

為MongoDB提供技術支援的10gen公司CEO凱文-賴安Dwight Merriman說:“我們公司成立於3月29日,我認為我們選擇的不是一個縫隙市場,相反,我認為我們會慢慢改變企業使用者市場。現在我們可以看到,MongoDB.org網站每月的下載量達到了3萬次,而幾個月前,下載量還為零”。

10gen公司CEO Dwight Merriman

MongoDB的名字源自一個形容詞humongous(巨大無比的),在向上擴充套件和快速處理大資料量方面,它會損失一些精度,在舊金山舉行的MondoDB大會上,Merriman說:“你不適宜用它來處理複雜的金融事務,如證券交易,資料的一致性可能無法得到保證”。

NoSQL資料庫都被貼上不同用途的標籤,如MongoDB和CouchDB都是面向文件的資料庫,但這並不意味著它們可以象JSON(JavaScript ObjectNotation,JavaScript物件標記)那樣以結構化資料形式儲存文字文件。

JSON被認為是XML的代替品,它是一個輕量級的,基於文字交換資料的標準,和XML一樣具有人類易讀的特性。簡單的JSON資料結構叫做物件,可能包括多種資料型別,如整型(int),字串(string),陣列(array),日期(date),物件(object)和位元組陣列(bytearray)。

面向文件的資料庫與關係資料庫有著顯著的區別,面向文件的資料庫用一個有組織的檔案來儲存資料,而不是用行來儲存資料,在MongoDB中,一組文件被看作是一個集合,在關係資料庫中,許多行的集合被看作是一張表。

但同時它們的操作又是類似的,關係資料庫使用select,insert,update和delete操作表中的資料,面向文件的資料庫使用query,insert,update和remove做意義相同的操作。

MongoDB中物件的最大尺寸被限制為4MB,但物件的數量不受限制,MongoDB可以通過叢集加快操作的執行速度,當資料庫變得越來越大時,可以向叢集增加伺服器解決效能問題。

Wordnik工程副總裁Tony Tam說他的公司有5百萬個文件,以前儲存在MySQL資料庫中,大約有1.5TB,一個月前遷移到MongoDB上了,Wordnik專門收集所有單詞的定義和資訊,因此資料量是非常大的,遷移到MongoDB後,Tony Tam說他感到更放心。

Tam說使用MySQL資料庫時,Wordnik專案一直都象是在顛簸的路上前行,資料表的凍結時間有時甚至超過了10秒,這是任何人都不能容忍的。每天會有大約200個新單詞出現,我們要負責收集,並要向資料庫增加1500個例子顯示它們的用法,我們希望寫入資料庫的時間只需要1秒。Tam說:“我們不關心一致性,前後兩個使用者的查詢結果不一定非得保持一致,我們本來就是時刻在做著更新,這一點我們無法保證”。

Wordnik系統就象是一個龐大的線上詞典,有很多人同時線上查詢,但同時我們也在做更新,使用MongoDB後,我們可以保持高速新增資料,不用擔心資料庫會出現堵塞。Tam在MondoDB大會上曾做過一個題為“Wordnik:從MySQL到MongoDB”的演講,他說他們公司只花了一天時間就從MySQL遷移到MongoDB上了。

延伸閱讀

Mongo是一個高效能,開源,無模式的文件型資料庫,它在許多場景下可用於替代傳統的關係型資料庫或鍵/值儲存方式。Mongo使用C++開發,提供了以下功能:

◆面向集合的儲存:適合儲存物件及JSON形式的資料。

◆動態查詢:Mongo支援豐富的查詢表示式。查詢指令使用JSON形式的標記,可輕易查詢文件中內嵌的物件及陣列。

◆完整的索引支援:包括文件內嵌物件及陣列。Mongo的查詢優化器會分析查詢表示式,並生成一個高效的查詢計劃。

◆查詢監視:Mongo包含一個監視工具用於分析資料庫操作的效能。

◆複製及自動故障轉移:Mongo資料庫支援伺服器之間的資料複製,支援主-從模式及伺服器之間的相互複製。複製的主要目標是提供冗餘及自動故障轉移。

◆高效的傳統儲存方式:支援二進位制資料及大型物件(如照片或圖片)。

◆自動分片以支援雲級別的伸縮性(處於早期alpha階段):自動分片功能支援水平的資料庫叢集,可動態新增額外的機器。

MongoDB的主要目標是在鍵/值儲存方式(提供了高效能和高度伸縮性)以及傳統的RDBMS系統(豐富的功能)架起一座橋樑,集兩者的優勢於一身。根據官方網站的描述,Mongo適合用於以下場景:

◆網站資料:Mongo非常適合實時的插入,更新與查詢,並具備網站實時資料儲存所需的複製及高度伸縮性。

◆快取:由於效能很高,Mongo也適合作為資訊基礎設施的快取層。在系統重啟之後,由Mongo搭建的持久化快取層可以避免下層的資料來源過載。

◆大尺寸,低價值的資料:使用傳統的關係型資料庫儲存一些資料時可能會比較昂貴,在此之前,很多時候程式設計師往往會選擇傳統的檔案進行儲存。

◆高伸縮性的場景:Mongo非常適合由數十或數百臺伺服器組成的資料庫。Mongo的路線圖中已經包含對MapReduce引擎的內建支援。

◆用於物件及JSON資料的儲存:Mongo的BSON資料格式非常適合文件化格式的儲存及查詢。

自然,MongoDB的使用也會有一些限制,例如它不適合:

◆高度事務性的系統:例如銀行或會計系統。傳統的關係型資料庫目前還是更適用於需要大量原子性複雜事務的應用程式。

◆傳統的商業智慧應用:針對特定問題的BI資料庫會對產生高度優化的查詢方式。對於此類應用,資料倉庫可能是更合適的選擇。

◆需要SQL的問題

MongoDB支援OS X、Linux及Windows等作業系統,並提供了Python,PHP,Ruby,Java及C++語言的驅動程式,社群中也提供了對Erlang及.NET等平臺的驅動程式。(

漫畫:MongoDB身上的優勢和劣勢

SQL or NoSQL?That’s a question!SQL 與 NoSQL 的爭論從來沒有停息過,但其實任何一種技術都不會是適合一切應用場景的,重要的是你要充分了解自己的需求,再充分了解你要選擇的技術的優劣。

下面是一個關於 MongoDB 優缺點的列表,希望對打算使用 MongoDB 的同學,能有一些作用:

優勢:

快速!(當然,這和具體的應用方式有關,通常來說,它比一般的關係型資料庫快5位左右。)

很高的可擴充套件性 – 輕輕鬆鬆就可實現PB級的儲存(但是可能我們並不需要PB級的儲存,10TB可能就夠了)

他有一個很好的 replication 模式 (replica sets)

有很完善的Java API

他的儲存格式是Json的,這對Java來說非常好處理,對javascirpt亦然。

運維起來非常方便,你不用專門為它安排一個管理員。

它有一個非常活躍的社群(我提出的一個bug在20分鐘內就能得到修復。多謝Elliot)

他的版本控制非常清楚。

MongoDB 背後的公司(10gen)已經準備好了明天在 MongoDB 上面的投入的資金了。

劣勢

應用經驗缺乏,我們都沒有相關NoSQL 產品的使用經驗。

專案相對來說還比較新。

和以往的儲存相比,資料的關係性操作不再存在。

另附趣圖一張:

詳細分析Memcached快取與Mongodb資料庫的優點與作用

本文詳細講下Memcached和Mongodb一些看法,以及結合應用有什麼好處,希望看到大家的意見和補充。

  Memcached

  Memcached的優勢我覺得總結下來主要體現在:

  1) 分散式。可以由10臺擁有4G記憶體的機器,構成一個40G的記憶體池,如果覺得還不夠大可以增加機器,這樣一個大的記憶體池,完全可以把大部分熱點業務資料儲存進去,由記憶體來阻擋大部分對資料庫讀的請求,對資料庫釋放可觀的壓力。

  2) 單點。如果Web伺服器或App伺服器做負載均衡的話,在各自記憶體中儲存的快取可能各不相同,如果資料需要同步的話,比較麻煩(各自自己過期,還是分發資料同步?),即使資料並不需要同步,使用者也可能因為資料的不一致而產生使用者體驗上的不友好。

  3) 效能強。不用懷疑和資料庫相比確實是,根源上還是記憶體的讀寫和磁碟讀寫效率上幾個數量級的差距。有的時候我們在抱怨資料庫讀寫太差的情況下可以看看磁碟的IO,如果確實是瓶頸的話裝啥強勁的資料庫估計也檔不了,強不強無非是這個資料庫多少充分的利用了記憶體。

  但是也不太建議在任何情況下使用Memcached替代任何快取:

  1) 如果Value特別大,不太適合。因為在預設編譯下Memcached只支援1M的Value(Key的限制到不是最大的問題)。其實從實踐的角度來說也 不建議把非常大的資料儲存在Memcached中,因為有序列化反序列化的過程,別小看它消耗的CPU。說到這個就要提一下,我一直覺得 Memcached適合面向輸出的內容快取,而不是面向處理的資料快取,也就是不太適合把大塊資料放進去拿出來處理之後再放進去,而是適合拿出來就直接給輸出了,或是拿出來不需要處理直接用。

  2) 如果不允許過期,不太適合。Memcached在預設情況下最大30天過期,而且在記憶體達到使用限制後它也會回收最少使用的資料。因此,如果我們要把它當 作static變數的話就要考慮到這個問題,必須有重新初始化資料的過程。其實應該這麼想,既然是快取就是拿到了存起來,如果沒有必定有一個重新獲取重新快取的過程,而不是想著它永遠存在。

  在使用Memcached的過程中當然也會有一些問題或者說最佳實踐:

  1) 清除部分資料的問題。Memcached只是一個Key/Value的池,一個公共汽車誰都可以上。我覺得對於類似的公共資源,如果用的人都按照自己的規 則來的話很容易出現問題。因此,最好在Key值的規範上上使用類似名稱空間的概念, 每一個使用者都能很明確的知道某一塊功能的Key的範圍,或者說字首。帶來的好處是我們如果需要清空的話可以根據這個規範找到我們自己的一批Key然後再去 清空,而不是清空所有的。當然有人是採用版本升級的概念,老的Key就讓它過去吧,到時候自然會清空,這也是一種辦法。不過Key有規範總是有好處的,在 統計上也方便一點。

  2) Value的組織問題。也就是說我們存的資料的粒度,比如要儲存一個列表,是一個儲存在一個鍵值還是統一儲存為一個鍵值,這取決於業務。如果粒度很小的話最好是在獲取的時候能批量獲取,在儲存的時候也能批量儲存。對於跨網路的呼叫次數越少越好,可以想一下,如果一個頁面需要輸出100行資料,每一個數據都需要獲取一次,一個頁面進行上百次連線這個效能會不會成問題。

  那麼Memcached主要用在哪些功能上呢?

  其實我覺得平時能想到在記憶體中做快取的地方我們都可以考慮下是不是可以去適用分散式快取,但是主要的用途還是用來在前端或中部擋一下讀的需求來釋放Web伺服器App伺服器以及DB的壓力。

下面講講Mongodb。

Mongodb

  Mongodb是一款比較優良的非關係型資料庫的文件型的資料庫。它的優勢主要體現在:

  1) 開源。意味著即使我們不去改也可以充分挖掘它,MS SQL除了看那些文件,誰又知道它內部如何實現。

  2) 免費。意味著我們可以在大量垃圾伺服器上裝大量的例項,即使它效能不怎麼高,也架不住非常多的點啊。

  3) 效能高。其它沒比較過,和MS SQL相比,同樣的應用(主要是寫操作)一個撐500使用者就掛了,一個可以撐到2000。在資料量上到百萬之後,即使沒索引,MS SQL的插入效能下降的也一塌糊塗。其實任何事物都有相對性的,在變得複雜變得完善了之後會犧牲一部分的效能,MS SQL體現的是非常強的安全性資料完整性,這點是Mongodb辦不到的。

  4) 配置簡單並且靈活。在生產環境中對資料庫配置故障轉移群集和讀寫分離的資料庫複製是很常見的需求,MS SQL的配置繁瑣的步驟還是很恐怖的,而Mongodb可以在五分鐘之內配置自己所需要的故障轉移組,讀寫分離更是隻需要一分鐘。靈活性體現在,我們可以配置一個M一個S,兩個M一個S(兩個M寫入的資料會合併到S上供讀取),一個M兩個S(一個M寫入的資料在兩個S上有映象),甚至是多個M多個S(理論上可以建立10個M,10個S,我們只需要通過輪詢方式隨便往哪個M上寫,需要讀的時候也可以輪訓任意一個S,當然我們要知道不可能保證在同一時間所有的 S都有一致的資料)。那麼也可以配置兩個M的對作為一套故障轉移群集,然後這樣的群集配置兩套,再對應兩個S,也就是4個M對應2個S,保證M點具有故障 轉移。

  5) 使用靈活。在之前的文章中我提到甚至可以通過SQL到JS表示式的轉換讓Mongodb支援SQL語句的查詢,不管怎麼說Mongodb在查詢上還是很方便的。

  之前也說過了,並不是所有資料庫應用都使用採用Mongodb來替代的,它的主要缺點是:

  1) 開源軟體的特點:更新快,應用工具不完善。由於更新快,我們的客戶端需要隨著它的更新來升級才能享受到一些新功能,更新快也意味著很可能在某一階段會缺乏某個重要功能。另外我們知道MS SQL在DEV/DBA/ADM多個維度都提供了非常好的GUI工具對資料庫進行維護。而Mongodb雖然提供了一些程式,但是並不是非常友好。我們的 DBA可能會很鬱悶,去優化Mongodb的查詢。

  2) 操作事務。Mongodb不支援內建的事務(沒有內建事務不意味著完全不能有事務的功能),對於某些應用也就不適合。不過對於大部分的網際網路應用來說並不存在這個問題。

  在使用Mongodb的過程中主要遇到下面的問題:

  1) 真正的橫向擴充套件?在使用Memcached的過程中我們已經體會到這種爽了,基本可以無限的增加機器來橫向擴充套件,因為什麼,因為我們是通過客戶端來決定鍵值儲存在那個例項上,在獲取的時候也很明確它在哪個例項上,即使是一次性獲取多個鍵值,也是同樣。而對於資料庫來說,我們通過各種各樣的方式進行了 Sharding,不說其它的,在查詢的時候我們根據一定的條件獲取批量的資料,怎麼樣去處理?比如我們按照使用者ID去分片,而查詢根本不在乎使用者ID, 在乎的是使用者的年齡和教育程度,最後按照姓名排序,到哪裡去取這些資料?不管是基於客戶端還是基於服務端的Sharding都是非常難做的,並且即使有了 自動化的Sharding效能不一定能有保障。最簡單的是儘量按照功能來分,再下去就是歷史資料的概念,真正要做到實時資料分散在各個節點,還是很困難。

  2) 多執行緒,多程序。在寫入速度達不到預期的情況下我們多開幾個執行緒同時寫,或者多開幾個Mongodb程序(同一機器),也就是多個數據庫例項,然後向不同 的例項去寫。這樣是否能提高效能?很遺憾,非常有限,甚至可以說根本不能提高。為什麼使用Memcached的時候多開執行緒可以提高寫入速度?那是因為內 存資料交換的瓶頸我們沒達到,而對於磁碟來說,IO的瓶頸每秒那麼幾十兆的是很容易達到的,一旦達到這個瓶頸了,無論是開多少個程序都無法提高效能了。還 好Mongodb使用記憶體對映,看到記憶體使用的多了,其實我對它的信心又多了一點(記憶體佔用多了我覺得CPU更容易讓它不閒著),怕就怕某個DB不使用什 麼記憶體,看著IO瓶頸到了,記憶體和CPU還是吃不飽。

  Memcached和Mongodb的配合

  其實有了Memcached和Mongodb我們甚至可以讓80%以上的應用擺脫傳統關係型資料庫。我能想到它們其實可以互相配合彌補對方的不足:

  Memcached適合根據Key儲存Value,那麼有的時候我們並不知道需要讀取哪些Key怎麼辦呢?我在想是不是可以把Mongodb或 說資料庫當作一個原始資料,這份原始資料中分為需要查詢的欄位(索引欄位)和普通的資料欄位兩部分,把大量的非查詢欄位儲存在Memcached中,小粒 度儲存,在查詢的時候我們查詢資料庫知道要獲取哪些資料,一般查詢頁面也就顯示20-100條吧,然後一次性從Memcached中獲取這些資料。也就是 說,Mongodb的讀的壓力主要是索引欄位,而資料欄位只是在快取失效的時候才有用,使用Memcached擋住大部分實質資料的查詢。反過來說,如果我們要清空Memcached中的資料也知道要清空哪些Key。

MongoDB 文件閱讀筆記 —— 優雅的 NoSQL

NoSQL 資料庫在上年炒得很熱,於是我也萌生了使用 NoSQL 資料庫寫一個應用的想法。首先來認識一下 NoSQL。NoSQL 是一個縮寫,含義從最初的 No-SQL 到現在已經成為了 Not-Only-SQL。確實後面一種解釋比較符合 NoSQL 的使用場景。

現在網路上被人所知的 NoSQL 資料庫可以在這個網頁(http://nosql-database.org)看到。這個列表林林總總一大堆,要選擇哪個資料庫入手呢?

相關推薦

MongoDB全面總結

原文地址:http://blog.csdn.net/jakenson/article/details/7060431  MongoDB的內部構造《MongoDB The Definitive Guide》 MongoDB的官方文件基本是how to d

關於Mongodb全面總結

MongoDB的內部構造《MongoDB The Definitive Guide》 MongoDB的官方文件基本是how to do的介紹,而關於how it worked卻少之又少,本人也剛買了《MongoDB TheDefinitive Guide》的影印

關於Mongodb全面總結,學習mongodb的人,可以從這裡開始!

原文地址:http://blog.csdn.net/jakenson/article/details/7060431  MongoDB的內部構造《MongoDB The Definitive Guide》 MongoDB的官方文件基本是how to do的介紹,而

[MongoDB知識體系] 一文全面總結MongoDB知識體系

# ♥MongoDB教程 - Mongo知識體系詳解♥ > 本系列將給大家構建MongoDB全域性知識體系。@pdai - [♥MongoDB教程 - Mongo知識體系詳解♥](#mongodb教程---mongo知識體系詳解) - [知識體系](#知識體系) - [學習要點](#學習要點)

全面總結: Golang 調用 C/C++,例子式教程

imp linu cstring -fpic blog div linux vid 文件 作者:林冠宏 / 指尖下的幽靈 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblog

對前端異常window error捕獲的全面總結

value type dde style oct alert 參數 htm 異常捕獲 對於前端的異常捕獲,我們都會知道onerror事件,但針對window的error事件的用法,其實是有區別的。 方式一: window.onerror = handleOnError 1.

Hadoop效能調優全面總結

一、 Hadoop概述 隨著企業要處理的資料量越來越大,MapReduce思想越來越受到重視。Hadoop是MapReduce的一個開源實現,由於其良好的擴充套件性和容錯性,已得到越來越廣泛的應用。 Hadoop實現了一個分散式檔案系統(Hadoop Distributed File Sys

JAVA類的全面總結

java是面向物件: 下面解釋什麼面向物件 JAVA操作都是類中操作如上圖Cat類,例項化可以在main函式中 那麼java本身就是類操作,為什麼還要學習繼承多型介面包? 官方回答:可讀性強,安全性高,程式碼簡化,維護性高,方便查詢錯誤等 下面我要從現實生活的角度

android APK瘦身全面總結——如何從32.6M到13.6M

前言 之前我簡單介紹了關於svg圖片瘦身的問題,在公司,瘦身這個問題是我提出來的,所以這鍋我背了。公司專案是32.6M,我給自己的要求就是低於20M。上週花了一個星期瘦身,至於為什麼花了一週,主要是svg適配問題我被搞矇蔽了。然後發現還要改大量程式碼,想想也就算了,又換了另一種瘦身方法。 很多人是因

MySql知識點全面總結

結構化查詢語言SQL概述 SQL(Structured Query Language) 是結構化查詢語言的縮寫。 SQL是在關係資料庫上執行資料操作、檢索及維護所使用的標準語言,可以用來查詢資料,操縱資料,定義資料,控制資料,所有資料庫都使用相同或者相似的語言。 SQL可分為:

Flutter填坑全面總結

版權宣告:本文首發在公眾號Flutter那些事,未經授權,嚴禁轉載。 Flutter是一個新的跨平臺開發的工具,博主也玩了一段時間,一步步的踩著坑摸石頭過河,這其中受盡了各種各樣的坑,各種谷歌,stackoverflow,Flutter官網等查資料,然而有些問題還是不能及時解決,於是就自己嘗試著慢慢的摸索除

根據整個集訓情況完成的全面總結反思

天天墊底還總結啥馬上就退役了 知識點 經典套路不會做 資料結構就寫錯 結論也不會做 顯然的結論顯然不出來 想題總是跳坑裡,無法自拔(要及時換思路啊) 博弈啥都不會!! 期望的線性性不會!! 我發現我連聯賽都上不了200分了 策略 發現時間有點吃緊(想題過久) 最後

索引失效的情況有哪些?索引何時會失效?(全面總結

雖然你這列上建了索引,查詢條件也是索引列,但最終執行計劃沒有走它的索引。下面是引起這種問題的幾個關鍵點。 列與列對比 某個表中,有兩列(id和c_id)都建了單獨索引,下面這種查詢條件不會走索引 select * from test where id=c_id; 這種情

全面總結Oracle中的分割槽表(精)

何時使用分割槽表 分割槽表是對錶按照規則進行劃分,這個是要根據業務場景來確定的。 建議值 1 大於2G的表 2 分割槽鍵必須反應業務需求,CUDR儘量不要跨分割槽操作 如果通過有效隔離,全表掃描就變成了分割槽掃描,降低IO,但如果已經使用索引,且結果集較小時,做分割槽不一定會

android開發之svg全面總結

VectorDrawable Vector Drawable是Google從Android 5.0開始引入的一個新的Drawable子類,能夠載入向量圖(低版本中需要做相容,如何相容低版本下文提及),android中vector Drawable通過配置xml再設定到要使用的控制元件

ViewPager 全面總結

一、簡介 Viewpager,檢視翻頁工具,提供了多頁面切換的效果。Android 3.0後引入的一個UI控制元件,位於v4包中。低版本使用需要匯入v4包,但是現在我們開發的APP一般不再相容3.0及以下的系統版本,另外現在大多數使用Android studio進行開發

Ajax的全面總結

Ajax 的全面總結 Ajax在前端開發中有著舉足輕重的地位,關於Ajax的使用和注意事項一直是一個重要的話題,藉此機會,本文希望對Ajax做一個全面的總結,徹底揭開Ajax的神祕面紗。 一.什麼是Ajax Ajax(Asynchronous JavaScript an

關於C++ const 的全面總結

    C++中的const關鍵字的用法非常靈活,而使用const將大大改善程式的健壯性,本人根據各方面查到的資料進行總結如下,期望對朋友們有所幫助。 Const 是C++中常用的型別修飾符,常型別是指使用型別修飾符const說明的型別,常型別的變數或物件的值是不能被更新的。 一、Const作用 如下表所示

vue元件通訊全面總結

寫在前面 元件間的通訊是是實際開發中非常常用的一環,如何使用對專案整體設計、開發、規範都有很實際的的作用,我在專案開發中對此深有體會,總結下vue元件間通訊的幾種方式,討論下各自的使用場景 文章對相關場景預覽 父->子元件間的資料傳遞 子->父元件間的資料傳遞 兄弟元件間的

2018全面總結阿里巴巴Java開發手冊

其實早在多年前,Google就已經把公司內部採用的所有語言的編碼規範(其稱為 Style Guide )都開源在Github上。這份清單中包括了 C++ 、 Objective-C 、 Java 、 Python 、 R 、 Shell 、 HTML/CSS 、 JavaScript 、 A