NoSql數(shù)據(jù)庫優(yōu)缺點
在優(yōu)勢方面主要體現(xiàn)在下面幾點:
簡單的擴(kuò)展
快速的讀寫
低廉的成本
靈活的數(shù)據(jù)模型
在不足方面主要有下面幾點:
不提供對SQL的支持
支持的特性不夠豐富
現(xiàn)有的產(chǎn)品不夠成熟
MongoDB簡介
MongoDB是用C++語言編寫的非關(guān)系型數(shù)據(jù)庫。特點是高性能、易部署掖蛤、易使用,存儲數(shù)據(jù)十分方便,主要特性有:+
面向集合存儲顺囊,易于存儲對象類型的數(shù)據(jù)
模式自由
支持動態(tài)查詢
支持完全索引姻乓,包含內(nèi)部對象
支持復(fù)制和故障恢復(fù)
使用高效的二進(jìn)制數(shù)據(jù)存儲,包括大型對象
文件存儲格式為BSON(一種JSON的擴(kuò)展)
MongoDB基本概念介紹
文檔(document)是MongoDB中數(shù)據(jù)的基本單元五辽,非常類似于關(guān)系型數(shù)據(jù)庫系統(tǒng)中的行(但是比行要復(fù)雜的多)
集合(collection)就是一組文檔办斑,如果說MongoDB中的文檔類似于關(guān)系型數(shù)據(jù)庫中的行,那么集合就如同表
MongoDB的單個計算機(jī)可以容納多個獨立的數(shù)據(jù)庫杆逗,每一個數(shù)據(jù)庫都有自己的集合和權(quán)限
MongoDB自帶簡潔但功能強大的JavaScript shell乡翅,這個工具對于管理MongoDB實例和操作數(shù)據(jù)作用非常大
每一個文檔都有一個特殊的鍵"_id",它在文檔所處的集合中是唯一的,相當(dāng)于關(guān)系數(shù)據(jù)庫中的表的主鍵
MongoDB數(shù)據(jù)類型
數(shù)據(jù)類型描述舉例
null表示空值或者未定義的對象{"x":null}
布爾值真或者假:true或者false{"x":true}
32位整數(shù) ? ? ? ? ?32位整數(shù)罪郊。shell是不支持該類型的蠕蚜,shell中默認(rèn)會轉(zhuǎn)換成64位浮點數(shù)
64位整數(shù) ? ? ? ? ?64位整數(shù)。shell是不支持該類型的悔橄,shell中默認(rèn)會轉(zhuǎn)換成64位浮點數(shù)
64位浮點數(shù) ? ? ?64位浮點數(shù)靶累。shell中的數(shù)字就是這一種類型{"x":3.14,"y":3}
字符串UTF-8字符串{"foo":"bar"}
符號shell不支持癣疟,shell會將數(shù)據(jù)庫中的符號類型的數(shù)據(jù)自動轉(zhuǎn)換成字符串
對象id文檔的12字節(jié)的唯一id{"id": ObjectId()}
日期從標(biāo)準(zhǔn)紀(jì)元開始的毫秒數(shù){"date":new Date()}
正則表達(dá)式 ? ? ?文檔中可以包含正則表達(dá)式挣柬,遵循JavaScript的語法 ?{"foo":/foobar/i}
代碼文檔中可以包含JavaScript代碼{"x":function() {}}
未定義undefined{"x":undefined}
數(shù)組值的集合或者列表{"arr": ["a","b"]}
內(nèi)嵌文檔 ? ? ? ? ?文檔可以作為文檔中某個key的value{"x":{"foo":"bar"}}
1 安裝MongoDB
MongoDB的安裝非常簡單,只需要將下載的MongoDB的壓縮文件解壓到任意目錄睛挚,并將其中的bin目錄加入到系統(tǒng)的path環(huán)境變量中即可凛忿。
2 啟動MongoDB
在啟動MongoDB之前,要手動創(chuàng)建一個存放MongoDB數(shù)據(jù)文件的目錄竞川,如D:\mongo_data在命令行執(zhí)行 mongod --dbpath=D:\mongo_data
小技巧:手動創(chuàng)建一個后綴為bat的文件店溢,文件名任意,內(nèi)容為: mongod --dbpath=D:\mongo_data委乌,雙擊此文件就可以啟動MongoDB服務(wù)床牧,
不用每次都到命令行執(zhí)行啟動命令
在啟動服務(wù)器的shell下可以鍵入Ctrl-C來完全的停止mongod的運行
3 連接到MongoDB服務(wù)器
重新開啟一個命令行 運行mongo命令
輸入mongo命令默認(rèn)連接到本地的名稱為test的數(shù)據(jù)庫,如果希望連接到遠(yuǎn)程數(shù)據(jù)庫遭贸,可以使用mongo ip:port
4 常用命令
數(shù)據(jù)庫操作
創(chuàng)建數(shù)據(jù)庫,使用命令 use 數(shù)據(jù)庫名稱
use 命令后跟的數(shù)據(jù)庫名戈咳,如果存在就進(jìn)入此數(shù)據(jù)庫,如果不存在就創(chuàng)建,所以這種創(chuàng)建方式又叫隱式創(chuàng)建
注意:使用命令use mydb1創(chuàng)建數(shù)據(jù)庫后著蛙,并沒有真正生成對應(yīng)的數(shù)據(jù)文件删铃,如果此時退出,此數(shù)據(jù)庫將被刪除踏堡,只有在此數(shù)據(jù)庫中創(chuàng)建集合后猎唁,才會真正生成數(shù)據(jù)文件
查看所有數(shù)據(jù)庫,使用命令 show dbs
查看當(dāng)前所在數(shù)據(jù)庫顷蟆,使用命令 db
集合操作
查看當(dāng)前數(shù)據(jù)庫中所有的集合诫隅,使用命令 show collections 或使用show tables
創(chuàng)建集合有兩種方式,顯示創(chuàng)建和隱式創(chuàng)建
顯示創(chuàng)建可以使用命令 db.createCollection("集合名稱")
隱式創(chuàng)建可以使用命令 db.集合名稱.insert({}),指創(chuàng)建集合并同時向集合中插入數(shù)據(jù),例如:db.customer.insert({name:”jack”})
刪除集合使用命令:db.集合名稱.drop()
向集合添加文檔帐偎,使用命令 db.集合名稱.insert({})逐纬,例如:db.user1.insert({name:”jack”,age:20})
可以使用下面的循環(huán)語句批量插入多個文檔
for(var i=0;i<1000;i++){
db.hjb.insert({name:”name”+i ,age:i});
}
還可以使用db.集合名稱.save({})向集合中添加文檔,save于insert不同之處為:
使用insert如果插入的文檔中_id已經(jīng)存在削樊,則不能插入豁生,類似于關(guān)系型數(shù)據(jù)庫中的主鍵沖突
save方法如果插入的文檔中_id已經(jīng)存在,則執(zhí)行更新
刪除集合中的文檔漫贞,使用命令 db.集合名稱.remove({刪除條件})甸箱,不加刪除條件為刪除集合中的所有文檔,
例如绕辖,db.c1.remove() 為刪除c1集合中的所有文檔摇肌,db.c1.remove({name:”user1”})為刪除c1集合中name為user1的文檔
查詢集合中的文檔擂红,可以使用命令 db.集合名稱.find({條件})仪际,或者使用 db.集合名稱.findOne() ?查詢第一個文檔
db.customer.find()
db.customer.find({name:"name5"}) 查詢customer集合中name為name5的文檔
查詢集合中的文檔,返回某些特定的鍵值
//返回除了age字段外的所有字段
db.user.find({age:0});
//返回tags=tennis除了comments的所有列
db.posts.find({tag:'tennis'},{comments:0})
//返回userid=16的name字段
db.user.find({userid:16},{name:1});
{"_id":16,"name":"user16"}
//返回x=john的所有z字段
db.things.find({x:"john"},{z:1});
查詢集合中的文檔 昵骤,使用條件表達(dá)式(<, <=, >, >=,!=)
//大于: field > value
db.collection.find({field:{$gt:value}});
//小于: field < value
db.collection.find({field:{$lt:value}});
//大于等于: field >= value
db.collection.find({field:{$gte:value}});
//小于等于: field <= value
db.collection.find({field:{$lte:value}});
//不等于: ?field != value
db.collection.find({field:{$ne:value}});
查詢集合中的文檔 树碱,統(tǒng)計(count)、排序(sort)变秦、分頁(skip成榜、limit)
db.customer.count();
db.customer.find().count();
db.customer.find({age:{$lt:5}}).count();
db.customer.find().sort({age:1}); 降序-1
db.customer.find().skip(2).limit(3);
db.customer.find().sort({age:-1}).skip(2).limit(3);
db.customer.find().sort({age:-1}).skip(2).limit(3).count();
db.customer.find().sort({age:-1}).skip(2).limit(3).count(0);
db.customer.find().sort({age:-1}).skip(2).limit(3).count(1);
查詢集合中的文檔 ,$all主要用來查詢數(shù)組中的包含關(guān)系,查詢條件中只要有一個不包含就不返回
db.c2.insert({name:"user1",post:[1,2,3,4,5]});
查詢集合中的文檔 ,$in蹦玫,類似于關(guān)系型數(shù)據(jù)庫中的IN
db.cunstomer.find({age:{$in:[3,5,7]}})
查詢集合中的文檔 ,$nin赎婚,與$in相反
db.customer.find({age:{$nin:[4]}})
查詢集合中的文檔 ,$or,相當(dāng)于關(guān)系型數(shù)據(jù)庫中的OR樱溉,表示或者的關(guān)系挣输,例如查詢name為user2或者age為3的文檔,命令為:
db.customer.find({$or:[{name:”user2”},{age:3}]})
查詢集合中的文檔 ,$nor福贞,表示根據(jù)條件過濾掉某些數(shù)據(jù)撩嚼,例如查詢name不是user2,age不是3的文檔,命令為:
db.customer.find({$nor:[{name:”user2”},{age:3}]})
查詢集合中的文檔 ,$exists完丽,用于查詢集合中存在某個鍵的文檔或不存在某個鍵的文檔恋技,例如查詢customer集合中存在name鍵的所有文檔,可以使用 db.customer.find({name:{$exists:1}})逻族,
$exists:1表示真蜻底,指存在
$exists:0表示假,指不存在
查詢集合中的文檔 瓷耙,類似于關(guān)系型數(shù)據(jù)庫朱躺,mongodb中也有游標(biāo)的概念
var x =db.customer.find()
x.hasNext()
x.next()
更新集合中的文檔,語法如下:
db.collection.update(criteria,objNew,upsert,multi)
參數(shù)說明:
criteria:用于設(shè)置查詢條件的對象
objNew:用于設(shè)置更新內(nèi)容的對象
upsert:如果記錄已經(jīng)存在搁痛,更新它长搀,否則新增一個記錄,取值為0或1
multi:如果有多個符合條件的記錄鸡典,是否全部更新源请,取值為0或1
注意:默認(rèn)情況下,只會更新第一個符合條件的記錄
一般情況下后兩個參數(shù)分別為0,1 彻况,即:
db.collection.update(criteria,objNew,0,1)
更新集合中的文檔,將集合中name為user1的文檔改成name為jack
db.c1.update({name:"user1"},{name:"jack"})
這種修改有兩個問題谁尸,就是會使用新文檔覆蓋原來的文檔,如果原來文檔有多個鍵纽甘,修改后就有可能被覆蓋只剩下一個鍵了
第二個問題為即使符合更新條件的文檔有多個也只會更新第一個符合條件的記錄
更新集合中的文檔, $set 用來指定一個鍵的值良蛮,如果這個鍵不存在,則創(chuàng)建它悍赢。例如:
給name為user1的文檔添加address决瞳,可以使用命令:
db.c1.update({name:”user1”},{$set:{address:”bj”}},0,1)
將name為user1的文檔修改address為tj,其它鍵值對不變,命令為:
db.c1.update({name:”user1”},{$set:{address:”tj”}},0,1)
更新集合中的文檔,使用 $inc 將集合中name為user1的age加1左权,其它鍵不變, $inc表示使某個鍵值加減指定的數(shù)值
db.c1.update({name:"user1"},{$inc:{age:1}})
db.c1.find()
更新集合中的文檔, $unset 用來刪除某個鍵皮胡,例如刪除name為user1的文檔中的address鍵,可以使用命令:
db.c1.update({name:”user1”},{$unset:{address:1}},0,1)
5 索引
索引就是用來加速查詢的赏迟。數(shù)據(jù)庫索引與書籍的索引類似:有了索引就不需要翻遍整本書屡贺,數(shù)據(jù)庫則可以直接在索引中查找,
使得查找速度能提高幾個數(shù)量級锌杀。在索引中找到條目以后甩栈,就可以直接跳轉(zhuǎn)到目標(biāo)文檔的位置。
創(chuàng)建索引
創(chuàng)建普通索引糕再,使用命令 db.collection.ensureIndex({key:1})
查看關(guān)于索引的相關(guān)信息量没,使用命令 db.collection.stats()
查看查詢使用索引的情況,使用命令 ? db.collection.find({key:value}).explain()
刪除索引亿鲜,使用命令 db.collection.dropIndex({key:1})
刪除集合允蜈,也會將集合中的索引全部刪除
?explain是非常有用的工具冤吨,會幫助你獲得查詢方面諸多有用的信息。只要對游標(biāo)調(diào)用該方法饶套,就可以得到查詢細(xì)節(jié)漩蟆。explain會返回一個文檔,而不是游標(biāo)本身妓蛮。
如:>db.test.find().explain()
{"cursor" : "BasicCursor",
"nscanned" : 1,
"nscannedObjects" : 1,
"n" : 1,
"millis" : 0,
"nYields" : 0,
"nChunkSkips" : 0,
"isMultiKey" : false,
"indexOnly" : false,
"indexBounds" : {}?}
explain會返回查詢使用的索引情況怠李,耗時和掃描文檔數(shù)的統(tǒng)計信息。
"cursor":"BasicCursor"表示沒有使用索引蛤克。
"nscanned":1 表示查詢了多少個文檔捺癞。
"n":1 表示返回的文檔數(shù)量。
"millis":0 表示整個查詢的耗時构挤。
6 固定集合(capped collection)
固定集合指的是事先創(chuàng)建而且大小固定的集合 髓介。
固定集合特性:固定集合很像環(huán)形隊列,如果空間不足筋现,最早的文檔就會被刪除唐础,為新的文檔騰出空間。一般來說矾飞,固定集合適用于任何想要自動淘汰過期屬性的場景一膨,沒有太多的操作限制。
創(chuàng)建固定集合使用命令:db.createCollection(“collectionName”,{capped:true,size:100000,max:100});
size指定集合大小洒沦,單位為KB豹绪,max指定文檔的數(shù)量
當(dāng)指定文檔數(shù)量上限時,必須同時指定大小申眼。淘汰機(jī)制只有在容量還沒有滿時才會依據(jù)文檔數(shù)量來工作瞒津。要是容量滿了,淘汰機(jī)制會依據(jù)容量來工作豺型。
將普通集合轉(zhuǎn)換為固定集合 :
db.runCommand({convertToCapped:“collectionName",size:10000,max:100});
7 備份(mongodump)和恢復(fù)(mongorestore)
MongoDB提供了備份和恢復(fù)的功能仲智,分別是MongoDB下載目錄下的mongodump.exe和mongorestore.exe文件
備份數(shù)據(jù)使用下面的命令:
>mongodump -h dbhost -d dbname -o dbdirectory
-h:MongDB所在服務(wù)器地址买乃,例如:127.0.0.1姻氨,當(dāng)然也可以指定端口號:127.0.0.1:27017
-d:需要備份的數(shù)據(jù)庫實例,例如:test
-o:備份的數(shù)據(jù)存放位置剪验,例如:c:\data\dump肴焊,當(dāng)然該目錄需要提前建立,在備份完成后功戚,系統(tǒng)自動在dump目錄下建立一個test目錄娶眷,這個目錄里面存放該數(shù)據(jù)庫實例的備份數(shù)據(jù)。
恢復(fù)數(shù)據(jù)使用下面的命令:
>mongorestore -h dbhost -d dbname -directoryperdb dbdirectory
-h:MongoDB所在服務(wù)器地址
-d:需要恢復(fù)的數(shù)據(jù)庫實例届宠,例如:test烁落,當(dāng)然這個名稱也可以和備份時候的不一樣,比如test2
-directoryperdb:備份數(shù)據(jù)所在位置豌注,例如:c:\data\dump\test
8 導(dǎo)入(mongoimport)和導(dǎo)出(mongoexport)
導(dǎo)出數(shù)據(jù)可以使用命令:
mongoexport -h dbhost -d dbname -c collectionName -o output
參數(shù)說明:
-h ?數(shù)據(jù)庫地址
-d 指明使用的庫
-c 指明要導(dǎo)出的集合
-o 指明要導(dǎo)出的文件名
導(dǎo)入數(shù)據(jù)可以使用命令:
mongoimport -h dbhost -d dbname -c collectionname 文件的地址...
參數(shù)說明:
-h ?數(shù)據(jù)庫地址
-d 指明使用的庫
-c 指明要導(dǎo)入的集合
本地的文件地址...
9 安全和認(rèn)證
每個MongoDB實例中的數(shù)據(jù)庫都可以有許多用戶伤塌。如果開啟了安全性檢查,則只有數(shù)據(jù)庫認(rèn)證用戶才能執(zhí)行讀或者寫操作轧铁。
在認(rèn)證的上下文中每聪,MongoDB會將普通的數(shù)據(jù)作為admin數(shù)據(jù)庫處理。admin數(shù)據(jù)庫中的用戶被視為超級用戶(即管理員)齿风。
在認(rèn)證之后药薯,管理員可以讀寫所有數(shù)據(jù)庫,執(zhí)行特定的管理命令救斑,如listDatabases和shutdown童本。
在開啟安全檢查之前,一定要至少有一個管理員賬號脸候。
在admin數(shù)據(jù)庫中創(chuàng)建管理員賬號:
use admin;
db.addUser(“root”,”root”);
在test數(shù)據(jù)庫中創(chuàng)建普通賬號:
use test;
db.addUser(“zhangsan”,”123”);
db.addUser(“l(fā)isi”,”123”,true);
注意:用戶zhangsan巾陕,密碼為123,對test數(shù)據(jù)庫擁有讀寫權(quán)限
用戶lisi纪他,密碼為123鄙煤,對test數(shù)據(jù)庫擁有只讀權(quán)限
重新啟動數(shù)據(jù)庫服務(wù),并開啟安全檢查:
mongod --dbpath d:\mongo_data --auth
10 主從復(fù)制(主從集群 ) 重點內(nèi)容
主從復(fù)制是MongoDB最常用的復(fù)制方式茶袒。這種方式非常靈活梯刚,可用于備份、故障恢復(fù)薪寓、讀擴(kuò)展等亡资。
最基本的設(shè)置方式就是建立一個主節(jié)點和一個或者多個從節(jié)點,每個從節(jié)點要知道主節(jié)點的地址向叉。
運行mongod --master就啟動了主服務(wù)器锥腻。運行mongod --slave --source master_address 則啟動了從服務(wù)器,其中master_address就是上面主節(jié)點的地址母谎。
MongoDB的復(fù)制至少需要兩個服務(wù)器或者節(jié)點瘦黑。其中一個是主節(jié)點,負(fù)責(zé)處理客戶端請求奇唤,其它的都是從節(jié)點幸斥,負(fù)責(zé)映射主節(jié)點的數(shù)據(jù)。
主節(jié)點記錄在其上執(zhí)行的所有操作咬扇。從節(jié)點定期輪詢主節(jié)點獲得這些操作甲葬,然后對自己的數(shù)據(jù)副本執(zhí)行這些操作。由于和主節(jié)點執(zhí)行了
相同的操作懈贺,從節(jié)點就能保持與主節(jié)點的數(shù)據(jù)同步经窖。
主節(jié)點的操作記錄成為oplog(operation log)坡垫。oplog存儲在一個特殊的數(shù)據(jù)庫中,叫做local画侣。oplog就在其中的oplog.$main集合
里面葛虐。oplog中的每個文檔都代表主節(jié)點上執(zhí)行的一個操作。需要重點強調(diào)的是oplog只記錄改變數(shù)據(jù)庫狀態(tài)的操作棉钧。比如屿脐,查詢就
不再存儲在oplog中。這是因為oplog只是作為從節(jié)點與主節(jié)點保持?jǐn)?shù)據(jù)同步的機(jī)制宪卿。
為了方便演示的诵,可以在一臺計算機(jī)上來模擬主節(jié)點和從節(jié)點。在D盤創(chuàng)建兩個目錄master和slave佑钾,master目錄作為主節(jié)點的數(shù)據(jù)文件的目錄西疤,slave目錄作為從節(jié)點的數(shù)據(jù)文件的目錄。
注意:主節(jié)點和從節(jié)點要指定不同的端口休溶。
啟動主節(jié)點:mongod --dbpath d:\master --port 10000 --master
啟動從節(jié)點:mongod --dbpath d:\slave --port 10001 --slave --source localhost:10000
啟動成功后就可以連接主節(jié)點進(jìn)行操作了代赁,而這些操作會同步到從節(jié)點。
注意:主節(jié)點可以進(jìn)行增刪改查所有操作兽掰,而從節(jié)點只能進(jìn)行查詢的操作
11 副本集 replset
副本集就是有自動故障恢復(fù)功能的主從集群芭碍。
主從集群和副本集最大的區(qū)別就是副本集沒有固定的“主節(jié)點”;
整個集群會選出一個“主節(jié)點”孽尽,當(dāng)其掛掉后窖壕,又在剩下的從節(jié)點中選中其他節(jié)點為“主節(jié)點”,副本集總有一個活躍點(primary)和一個或多個備份節(jié)點(secondary)杉女。
以三個節(jié)點為例:
節(jié)點1:
HOST:localhost:10001
Log File:D:\mongodb\logs\node1\logs.txt
Data File:D:\mongodb\dbs\node1
節(jié)點2:
HOST:localhost:10002
Log File:D:\mongodb\logs\node2\logs.txt
Data File:D:\mongodb\dbs\node2
節(jié)點3:
HOST:localhost:10003
Log File:D:\mongodb\logs\node3\logs.txt
Data File:D:\mongodb\dbs\node3
啟動節(jié)點1:
mongod --dbpath D:\mongodb\dbs\node1 --logpath D:\mongodb\logs\node1\logs.txt --logappend --port 10001 --replSet itcast/localhost:10002? --master
啟動節(jié)點2:
mongod --dbpath D:\mongodb\dbs\node2 --logpath D:\mongodb\logs\node2\logs.txt --logappend --port 10002 --replSet itcast/localhost:10001
啟動節(jié)點3:??
mongod --dbpath D:\mongodb\dbs\node3 --logpath D:\mongodb\logs\node3\logs.txt --logappend --port 10003 --replSet itcast/localhost:10001,localhost:10002
初始化節(jié)點(只能初始化一次):隨便登錄一個節(jié)點,以10001為例
?mongo localhost:10001/admin
?db.runCommand({
"replSetInitiate":{"_id":“itcast",
"members":[{"_id":1,
"host":"localhost:10001",
"priority":3},
{"_id":2,"host":"localhost:10002","priority":2},{"_id":3,"host":"localhost:10003","priority":1}]}});
參數(shù)解釋:
--replSet? 指定副本集? 后面緊跟著副本集的名稱
--logappend 日志文件末尾添加
--port 指定端口號
db.runCommand({})? 初始化副本集
初始化文檔:
"_id":“itcast",? 指副本集的名稱
?"members":[...]? 副本集的服務(wù)器列表? 每個列表有個
?????????????? "_id": 每個服務(wù)器的唯一id,?
??????????????"host" 指定服務(wù)器的主機(jī),
??????????????"priority"設(shè)置優(yōu)先級瞻讽,默認(rèn)優(yōu)先級為1,可以是1-1000的數(shù)字
查詢當(dāng)前主庫,登錄10002
mongo localhost:10002
db.$cmd.findOne ( {ismaster: 1 } );
關(guān)閉10001服務(wù)Dos命令窗口,? 登錄10002查詢當(dāng)前主庫
mongo localhost:10002
db.$cmd.findOne ( {ismaster: 1 } );
默認(rèn)情況下從庫是不能進(jìn)行讀寫操作的設(shè)置從庫可讀(在從庫secondary上執(zhí)行):
rs.slaveOk ( );
12 分片(sharding)分布式存儲..
分片(sharding)是指將數(shù)據(jù)拆分熏挎,將其分散存在不同的機(jī)器上的過程速勇。有時也用分區(qū)(partitioning)來表示這個概念。
將數(shù)據(jù)分散到不同的機(jī)器上坎拐,不需要功能強大的大型計算機(jī)就可以儲存更多的數(shù)據(jù)烦磁,處理更多的負(fù)載。
MongoDB分片的基本思想就是將集合切分成小塊廉白。這些塊分散到若干片里面个初,每個片只負(fù)責(zé)總數(shù)據(jù)的一部分乖寒。
應(yīng)用程序不必知道哪片對應(yīng)哪些數(shù)據(jù)猴蹂,甚至不需要知道數(shù)據(jù)已經(jīng)被拆分了,所以在分片之前要運行一個路由進(jìn)程楣嘁,該進(jìn)程名為mongos磅轻。
這個路由器知道所有數(shù)據(jù)的存放位置珍逸,所以應(yīng)用可以連接它來正常發(fā)送請求。對應(yīng)用來說聋溜,它僅知道連接了一個普通的mongod谆膳。
路由器知道數(shù)據(jù)和片的對應(yīng)關(guān)系,能夠轉(zhuǎn)發(fā)請求到正確的片上撮躁。如果請求有了回應(yīng)漱病,路由器將其收集起來回送給應(yīng)用。
設(shè)置分片時把曼,需要從集合里面選一個鍵杨帽,用該鍵的值作為數(shù)據(jù)拆分的依據(jù)。這個鍵稱為片鍵(shard key)嗤军。
{name:"zhangsan",age:1}
用個例子來說明這個過程:假設(shè)有個文檔集合表示的是人員注盈。
如果選擇名字("name")作為片鍵,第一片可能會存放名字以A~F開頭的文檔叙赚,第二片存的G~P的名字老客,第三片存的Q~Z的名字。
隨著添加或者刪除片震叮,MongoDB會重新平衡數(shù)據(jù)胧砰,使每片的流量都比較均衡,數(shù)據(jù)量也在合理范圍內(nèi)苇瓣。
mongos就是一個路由服務(wù)器朴则,它會根據(jù)管理員設(shè)置的“片鍵”將數(shù)據(jù)分?jǐn)偟阶约汗芾淼膍ongod集群,數(shù)據(jù)和片的對應(yīng)關(guān)系以及相應(yīng)的配置信息保存在“config服務(wù)器”上钓简。
mongod:一個普通的數(shù)據(jù)庫實例乌妒,如果不分片的話,我們會直接連上mongod外邓。
步驟:
1撤蚊、創(chuàng)建三個目錄,分別存放兩個mongod服務(wù)的數(shù)據(jù)文件和config服務(wù)的數(shù)據(jù)文件
2损话、開啟config服務(wù)器 侦啸。mongos要把mongod之間的配置放到config服務(wù)器里面,所以首先開啟它丧枪,這里就使用2222端口光涂。 命令為:
mongod --dbpath E:\sharding\config_node --port 2222
3、開啟mongos服務(wù)器 拧烦。這里要注意的是我們開啟的是mongos忘闻,端口3333,同時指定下config服務(wù)器恋博。命令為:
mongos --port 3333 --configdb=127.0.0.1:2222
4齐佳、啟動mongod服務(wù)器 私恬。對分片來說,也就是要添加片了炼吴,這里開啟兩個mongod服務(wù)本鸣,端口分別為:4444,5555硅蹦。命令為:
mongod --dbpath E:\sharding\mongod_node1 --port 4444
mongod --dbpath E:\sharding\mongod_node2 --port 5555
5荣德、服務(wù)配置 。client直接跟mongos打交道童芹,也就說明我們要連接mongos服務(wù)器命爬,然后將4444,5555的mongod交給mongos,添加分片也就是addshard()辐脖。
6饲宛、開啟數(shù)據(jù)庫分片功能,命令很簡單 enablesharding(),這里就開啟test數(shù)據(jù)庫嗜价。
7艇抠、指定集合中分片的片鍵,這里就指定為person.name鍵久锥。
8家淤、通過mongos插入10w記錄,然后通過printShardingStatus命令查看mongodb的數(shù)據(jù)分片情況瑟由。
這里主要看三點信息:
? ① shards: ? ? 可以看到已經(jīng)別分為兩個片了絮重,shard0000和shard0001。
? ② databases::?這里有個partitioned字段表示是否分區(qū)歹苦,這里可以看到test已經(jīng)分區(qū)青伤。
? ③ chunks: ? ? 集合被砍成四段:
? ? ? ? ? ? 無窮小 —— jack0,
jack0 ——jack234813殴瘦,
jack234813——jack9999狠角,
jack9999——無窮大。
分區(qū)情況為:3:1蚪腋,從后面的 on shardXXXX也能看得出丰歌。