MongoDB介紹

一、原理簡介


MongoDB是一個介於關係數據庫和非關係數據庫之間的產品,是非關係數據庫當***能最豐富,最像關係數據庫的。

他支持的數據結構非常鬆散,是類似json的bjson格式,因此可以存儲比較複雜的數據類型。

Mongo最大的特點是他支持的查詢語言非常強大,其語法有點類似於面向對象的查詢語言,幾乎可以實現類似關係數據庫單表查詢的絕大部分功能,而且還支持對數據建立索引。


1.新的詞彙

(1)文檔 document 相當於javascript的document 在程序中可以理解爲對象

例子: {“name”:”喬布斯”,”age”:53}

上述例子是一個人的對象(Steve Jobs!!!)。名字是“喬布斯”,年齡是53,這就是一個文檔。類似於我們關係型數據庫中的一行。


(2)集合 collection 一組文檔被稱作集合,類似於關係型數據庫表


2.新的東西

(1)無模式

集合是無模式的,不像關係型數據庫一樣,訂好了幾列,那麼所有數據都是相同列,相同類型

例子: {“name”:”喬布斯”,”age”:53}

{“company”:”psychcn”}

上述例子是一個集合,它之中的文檔可以是鬆散的,不固定的。


但是這樣做的話,數據的分析會很難做,所以說從數據庫設計的角度,不建議將不同類型的文檔放入一個集合。


(2)ObjectId

在每個文檔生成時,假如不指定,MongoDB會默認給當前文檔加入一個值“_id”,

例子: {“name”:”喬布斯”,”age”:53} 在數據庫中保存後將變爲

{

“_id”: ObjectId(“4df80f149fd997035452344d”),

“name”:”喬布斯”,

“age”:53

}


ObjectId在單個集合中唯一。類似於我們的主鍵。但是它的生成和增長完全是MongoDB提我們做,

我們不用考慮自增和重複。所以在分佈式開發中優勢很高,MongoDB生來就是爲了解決分佈式問題而存在的


ObjectId的生成規則

Object爲12位數字


0 1 2 3 4 5 6 7 8 9 10 11

時 間 戳 機器 PID 計數器


3.BSON

MongoDB的文檔類似於JSON,在概念是也是一樣的。

但是JSON的表現能力有限,例如數據類型,JSON只有null,布爾,數字,字符串,數組和對象幾種類型。

所以MongoDB在JSON的基礎上添加了一些東西(具體參考官方文檔)。


3.設計例子

我們設計一個學生,課程兩個集合


|———————–|

| db.students |

|name:”學生1″ |

|address: |

| |

| |—————–| |

| |address:”和平西橋”| |

| |city:”北京” | |

| |province:”北京” | |

| |postcode:”100013″| |

| |_________________| |

|scores: |

| for_course: |

| grade:4.0 |

| |

| for_course: |

| grade:3.0 |

|_______________________|


|———————–|

| db.courses |

| |

| |————| |

| |name:”語文” | |

| |____________| |

| |

| |————| |

| |name:”數學” | |

| |____________| |

|_______________________|


一、操作使用


1.增加


拿之前設計好的student舉例

db.student.insert({“name”:”學生2″});


2.刪除


db.student.remove();

將會刪除student集合中所有文檔

如果按照條件


db.student.remove({“name”:”學生1″});

將會刪除所有name爲學生1的文檔


如果要整個刪除集合,那麼使用

db.drop_collection(“student”)要比remove快的多,但是這樣會將集合完全刪除,包括索引


3.更新


(1) 文檔替換

$inc

用新的文檔更新現有文檔,相當於模式的改變。使用文檔替換。具體參見書26頁


(2) 修改器

db.student.update({ “name” : “學生1″ },

{ “$set”: { “name” : “學生3″ } })

4.查詢


(1) 全部返回

select * from student

db.student.find();


(2) 指定返回某一項

select name from student

db.student.find({} ,{ “name” : 1 })

此時除了name被返回,_id也被返回,可以具體設置讓_id不返回


(3) 按照條件返回

select * from student where name=’學生1′

db.student.find({“name”,”學生1″})


(4) 查詢條件

小於 “$lt”

小於等於 “$lte”

大於 “$gt”

大於等於 “$gte”


例子,按年齡查找學生,找出18-30歲的學生


select * from student where age >= 18 and agedb.student.find({ “age” : { “$gte” : 18 , “$lte” : 30 } })


或者OR “$in”

select * from student where age in (18,19,20)

select * from student where age=18 or age =19 or age = 20

db.student.find({ “age” : { “$in” : [ 18 , 19 , 20 ] } })


否NOT “$not”

select * from student where age <> 18

db.student.find({ “age” : { “$not” : 18 })


排序 “$sort”

db.student.find({“age” : {“$sort”:1 }}) 升序排序

db.student.find({“age” : {“$sort”:-1 }}) 降序排序


5.特殊查詢 (不具體介紹,參見書50-55頁)

(1) 正則查詢,可以在查詢條件中使用正則表達式

(2) 查詢數組

(3) 查詢內嵌文檔,Mongo的特殊查詢。可以查詢文檔的子集


6.分頁

limit,skip


db.student.find().limit(100);

db.student.find().skip(100).limit(100)


大數據量時不建議採用skip進行分頁。詳情參見60頁


三、高可用性配置

1.主從複製


因爲我沒有做這個測試,所以這個在這裏不講解。詳情見書


2.副本集(推薦)

副本集(Replica Set) 就是有自動故障恢復功能的主從集羣,沒有固定的主節點,整個集羣會投票選舉出一個主節點。

各節點會有各自角色。


副本集會有一個主節點(primary)和一個或多個備份節點(secndary)


節點角色分爲三種:

1.standard 常規節點,存儲數據副本,參選投票,可能成爲活躍節點

2.passive 備份節點,存儲數據副本,參選投票,不能成爲活躍節點

3.arbiter 仲裁節點, 只參與投票,不存儲數據,不能成爲活躍節點


故障切換完全是自動的。當一個節點不可使用時,自動切換下一個投票選舉出的節點作爲主節點

也許投票者的票數會成爲平衡狀態,所以爲了避免這種情況,節點的優先級是不一樣的。如果優先級相同,數據較新的節點獲勝


配置方法:


創建一個目錄爲存放數據作爲準備


$ mkdir -p /data/node1 (集羣中各個計算機都應做設置)


啓動之前應當爲此副本集起一個名字,譬如我這個副本集的名字叫做cmi


接下來,啓動第一臺計算機

$ ./mongod –auth –dbpath /data/node1 –port 27017 –replSet cmi


另外可以啓動時告訴當前機子還有同伴機子。例如

$ ./mongod –auth –dbpath /data/node1 –port 27017 –replSet cmi/192.168.0.2:27018,192.168.0.3:27019


其他計算機皆可參照以上進行啓動


下面,要初始化副本集

用客戶端工具連上,使用以下命令

db.runCommand({“replSetInitiate” : {

“_id” : “cmi”,

“members” : [

{

"id" : 1,

"host" : "192.168.0.1:27017"

},

{

"id" : 2,

"host" : "192.168.0.2:27018"

}

]

}})


這樣就可以了。

另外可以在配置時將角色配上,

例如priority : 1 被動節點,arbiterOnly : true 仲裁節點


當其中某臺宕機時,數據庫日誌將會出現 某一臺Server down的信息

各幾秒後將會顯示 Master switch 192.168.0.x:27017 to 192.168.0.x:27018 這樣的字樣,此時假如宕機機器再啓動

會發現他已經是secondary狀態。


3.oplog

記錄所有改變數據庫狀態的操作

例如插入,更新,刪除,所以查詢就不在記錄範圍內

可以使用 –oplogSize 指定大小,單位是MB,建議將oplog設置的足夠大,因爲當oplog過小,最新的操作就會覆蓋老的操作,當數據庫併發插入更新量大時,從節點始終不能與主節點數據一致。

會造成數據不一致


3.同步

當從節點第一次啓動的時候,將會對主節點的數據進行完整的同步,這回相當耗費資源和時間。同步完成後,從節點查詢主節點的oplog,並進行操作,保證數據最新


4.備份

(1) 停機備份

將MongoDB安全停止,將數據目錄拷貝進行備份


(2) 不停機備份

使用mogodump

$ ./mongodump -d databasename -o backup

將名稱爲databasename的數據庫備份一份到backup目錄


這種備份的辦法是工具對運行的MongoDB做完整查詢,然後將查詢到的所有文檔寫入磁盤。

所以這種辦法進行備份,不能保證數據的實時性。


有一種保證實時性的辦法。

使用fsync和鎖


執行 db.runCommand({ “fsync”:1 ,”lock” :1 });

此時,MongoDB會鎖定數據庫,禁止任何插入或修改的動作,並將緩衝區的數據強制寫入硬盤。保證當前數據最新。

然後就可以複製一份數據庫目錄


如果數據庫運行在有快照功能的文件系統,例如LVM或EBS,那麼快照會非常快。

備份好後進行解鎖


db.$cmd.sys.unlock.findOne();


另外,做好使用從屬備份,當使用副本集時,基本就可以放心了,可以直接對從服務器進行上述操作


5.恢復

使用mongorestore恢復我們之前的一個數據庫備份


$ ./mongorestore -d databasename –drop backup


6.修復

db.repairDatabase()


四、安全


1.增加用戶

>use admin

>db.addUser(“abc”,”123″)

2.啓動時加入安全驗證

–auth


五、其他


1.寫入原理

先寫入內存,再寫入oplog,當到達指定時間後,將數據寫入硬盤。

在分佈式狀態下,宕機神馬的,都不怕。但是單機數據可靠性不太好,不過,MongoDB官方在1.8版針對單機可靠性出臺一個解決方案

如果在啓動MongoDB時加上–dur 則MongoDB 會在進行寫操作前記一份日誌,這和在其他一些數據庫中的binlog 類似,在MongoDB 數據文件損壞的情況下,可以使用此日誌來進行恢復。據說其對性能的影響不大。


2.一些需要注意的東西

(1) 啓動時加上 –auth來確保數據庫必須安全訪問

(2) 如果安全需要,那麼最好給數據庫綁定ip,使用 –bindip

(3) 數據庫啓動時,會啓動一個簡單的http服務,作爲監控狀態使用,端口號比使用的端口大1000,例如默認27017的http端口就在28017 如果不需要此服務,可以使用–nohttpinter-face


3.客戶端工具

1.MongoVUE.付費工具,我沒使用過

2.Rockmongo 類似於phpmyadmin的工具,我覺得很好用,下載windows版後,會自帶一個nginx服務。對中文支持很好


其實官方的自帶工具就很好了


六、附錄


如何安裝和使用MongoDB

1.安裝

Windows和linux皆可從官網下載zip或tar.gz包,解壓,到bin目錄。即可,不需要安裝

2.啓動

啓動前一定要建立一個數據庫存放目錄

新建一個文件夾

mongod –dbpath 數據庫目錄 –port 服務監聽端口,默認27017 –fork 守護進程方式運行 –auth 需要安全驗證 –bindip 綁定ip


其中–dbpath是必須,其他項均可酌情考慮。


3.bin目錄中文件說明

mongo 客戶端工具,同時也是一個shell,可以運行javascript

mongod 數據庫服務主文件

mongodump 數據庫備份工具

mongoexport 數據庫導出工具,可以導json和csv格式

mongoimport 數據庫導入工具

mongorestore 數據庫恢復工具

mongostat 數據庫監控工具

mongofiles 用戶導入導出GirdFS文件工具


4.範例

用一個cmd啓動數據庫服務,一個啓動客戶端連接

(1)啓動服務端

Windows下。進入bin目錄

mongod –dbpath D:/data –port 27017 –auth


(2)使用客戶端連接

mongo

use test //切換到數據庫

db.auth(“abc”,123) //加入沒有加入–auth可以忽略這一步


七、結束語


上述文檔就是我自2011年6月8日至2011年6月15日研究MongoDB的主要成果,有一部分我沒有太搞明白的地方我沒有講,例如分片。目前來講我覺得我們不太需要進行分片,可以當數據激增時再使用。


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