簡(jiǎn)介 MongoDB是一個(gè)開(kāi)源的,基于分布式的,面向文檔存儲(chǔ)的菲關(guān)系型數(shù)據(jù)庫(kù)??梢赃\(yùn)行在Windows、Unix、OSX、Solaris系統(tǒng)上,支持32位和64位應(yīng)用,提供多種編程語(yǔ)言的驅(qū)動(dòng)程序。MongoDB支持的數(shù)據(jù)結(jié)構(gòu)非常松散,是類似JSON的BSON格式,通過(guò)鍵值對(duì)的形式存儲(chǔ)數(shù)據(jù),可以存儲(chǔ)復(fù)雜的數(shù)據(jù)類型。 基本概念 文檔(document):文檔是MongoDB的核心概念,是數(shù)據(jù)的基本單元,類似于關(guān)系數(shù)據(jù)庫(kù)中的行。在MongoDB中,文檔表示為鍵值對(duì)的一個(gè)有序集。文檔一般使用如下的樣式來(lái)標(biāo)記: {'title':'hello!'} {'title':'hello!','recommend':5} {'title':'hello!','recommend':5,'author':{'firstname':'paul','lastname':'frank'}} 從上面的例子可以看到,文檔的值有不同的數(shù)據(jù)類型,甚至可以是一個(gè)完整的內(nèi)嵌文檔(最后一個(gè)示例的author就是一個(gè)文檔) 集合(collection):集合是一組文檔的集合,相當(dāng)于關(guān)系型數(shù)據(jù)庫(kù)中的數(shù)據(jù)表,MongoDB數(shù)據(jù)庫(kù)不是關(guān)系型數(shù)據(jù)庫(kù),沒(méi)有模式的概念。同一集合中的文檔可以有不同的形式。比如: {'name':'jack','age':19} 可以存在同一個(gè)集合當(dāng)中。 數(shù)據(jù)庫(kù)(database):多個(gè)文檔構(gòu)成集合,多個(gè)集合組成數(shù)據(jù)庫(kù)。一個(gè)MongoDB實(shí)例可以承載多個(gè)數(shù)據(jù)庫(kù),每個(gè)數(shù)據(jù)庫(kù)可以擁有0到多個(gè)集合。 MongoDB 的主要目標(biāo)是在鍵值對(duì)存儲(chǔ)方式(提供了高性能和高度伸縮性)以及傳統(tǒng)的 RDBMS(關(guān)系性數(shù)據(jù)庫(kù))系統(tǒng),集兩者的優(yōu)勢(shì)于一身。MongoDB適用于以下場(chǎng)景:
當(dāng)然 MongoDB 也有不適合的場(chǎng)景:
集群攻略 MongoDB在商用環(huán)境中,為了高可用性,通常都是以集群形式使用的,MongoDB的集群環(huán)境搭建非常簡(jiǎn)單,下面就作一個(gè)介紹。 主從模式 我們?cè)谑褂肕ySQL數(shù)據(jù)庫(kù)時(shí)廣泛采用的模式,采用雙機(jī)備份后主節(jié)點(diǎn)掛掉了后從節(jié)點(diǎn)可以接替主機(jī)繼續(xù)服務(wù)。所以這種模式比單節(jié)點(diǎn)的要可靠得多。 下面看一下怎么一步步搭建MongoDB的主從復(fù)制節(jié)點(diǎn): 1. 準(zhǔn)備兩臺(tái)機(jī)器 10.43.159.56 和 10.43.159.58。 10.43.159.56當(dāng)作主節(jié)點(diǎn), 10.43.159.58作為從節(jié)點(diǎn)。 2. 分別下載MongoDB安裝程序包。在10.43.159.56上建立文件夾/data/MongoDBtest/master,10.43.159.58建立文件夾/data/MongoDBtest/slave。 3. 在10.43.159.56啟動(dòng)MongoDB主節(jié)點(diǎn)程序。注意后面的這個(gè) “ –master ”參數(shù),標(biāo)示主節(jié)點(diǎn): mongod –dbpath /data/MongoDBtest/master–master 輸出日志如下,成功: [initandlisten] MongoDB starting :pid=18285 port=27017 dbpath=/data/MongoDBtest/master master=1 4. 在10.43.159.58啟動(dòng)MongoDB從節(jié)點(diǎn)程序。關(guān)鍵配置:指定主節(jié)點(diǎn)ip地址和端口 –source 10.43.159.56:27017 和標(biāo)示從節(jié)點(diǎn) –slave參數(shù): mongod –dbpath /data/MongoDBtest/slave–slave –source 10.43.159.56:27017 輸出日志如下,成功: [initandlisten] MongoDB starting : pid=17888port=27017 dbpath=/data/MongoDBtest/slave slave=1 日志顯示從節(jié)點(diǎn)從主節(jié)點(diǎn)同步復(fù)制數(shù)據(jù) : [replslave] repl: from host: 10.43.159.56:27017 這樣,主從結(jié)構(gòu)的MongoDB集群就搭建好了,是不是很簡(jiǎn)單? 下面我們來(lái)看看這個(gè)集群能做什么?先登錄到從節(jié)點(diǎn)shell上,執(zhí)行插入數(shù)據(jù): mongo 127.0.0.1:27017 > db.testdb.insert({'test3':'testval3'}); not master 可以看到 MongoDB的從節(jié)點(diǎn)是只能讀,不能執(zhí)行寫操作的。 那么如果主服務(wù)器掛掉,從服務(wù)器可以接替工作嗎? 可以試一下,強(qiáng)制關(guān)掉主節(jié)點(diǎn)上的MongoDB進(jìn)程,登錄在從節(jié)點(diǎn)上,再次執(zhí)行插入數(shù)據(jù): > db.testdb.insert({'test3':'testval3'}); not master 看來(lái)從節(jié)點(diǎn)并沒(méi)有自動(dòng)接替主節(jié)點(diǎn)的工作,那就只有人工處理了,停止從節(jié)點(diǎn),再以master的方式啟動(dòng)從節(jié)點(diǎn),由于從節(jié)點(diǎn)上數(shù)據(jù)跟主節(jié)點(diǎn)一樣,此時(shí)從節(jié)點(diǎn)是可以替代主節(jié)點(diǎn)工作的,這屬于人工切換。 此外,我們可以搭建多個(gè)從節(jié)點(diǎn),實(shí)現(xiàn)數(shù)據(jù)庫(kù)的讀寫分離,比如主節(jié)點(diǎn)負(fù)責(zé)寫,多個(gè)從節(jié)點(diǎn)負(fù)責(zé)讀,對(duì)于移動(dòng)APP,絕大部分操作都是讀操作,可以實(shí)現(xiàn)負(fù)荷分擔(dān)。 那么,搭建了這套主從結(jié)構(gòu)的集群是不是就能應(yīng)付商用環(huán)境呢?我們發(fā)現(xiàn)還是有幾個(gè)問(wèn)題亟待解決的:
解決這幾個(gè)問(wèn)題就要靠下面介紹的副本集模式了。 副本模式 MongoDB官方已經(jīng)不建議使用主從模式了,替代方案是采用副本集的模式,那什么是副本集呢?簡(jiǎn)單地說(shuō),副本集就是有自動(dòng)故障恢復(fù)功能的主從集群,或者說(shuō)主從模式其實(shí)就是一個(gè)單副本的應(yīng)用,沒(méi)有很好的擴(kuò)展性和容錯(cuò)性。而副本集具有多個(gè)副本保證了容錯(cuò)性,就算一個(gè)副本掛掉了還有很多副本存在,更棒的是副本集很多地方都是自動(dòng)化的,它為你做了很多管理工作。聰明的讀者已經(jīng)發(fā)現(xiàn),主從模式的第一個(gè)問(wèn)題手工切換已經(jīng)得到解決了,難怪MongoDB官方強(qiáng)烈推薦使用這種模式。我們來(lái)看看MongoDB副本集的架構(gòu)圖: 由圖可以看到客戶端連接到整個(gè)副本集,不關(guān)心具體哪一臺(tái)機(jī)器是否掛掉。主服務(wù)器負(fù)責(zé)整個(gè)副本集的讀寫,副本集定期同步數(shù)據(jù)備份,一旦主節(jié)點(diǎn)掛掉,副本節(jié)點(diǎn)就會(huì)選舉一個(gè)新的主服務(wù)器,這一切對(duì)于應(yīng)用服務(wù)器不需要關(guān)心。我們看一下主服務(wù)器掛掉后的架構(gòu): 副本集中的副本節(jié)點(diǎn)通過(guò)心跳機(jī)制檢測(cè)到主節(jié)點(diǎn)掛掉后,就會(huì)在集群內(nèi)發(fā)起主節(jié)點(diǎn)的選舉機(jī)制,自動(dòng)選舉一位新的主服務(wù)器。So Cool!讓我們趕緊來(lái)部署一下! 官方推薦的副本集機(jī)器數(shù)量為至少3個(gè)(官方說(shuō)副本集數(shù)量最好是奇數(shù)),那我們也按照這個(gè)數(shù)量配置測(cè)試。 1. 準(zhǔn)備三臺(tái)機(jī)器 10.43.159.56、 10.43.159.58、10.43.159.60。10.43.159.56當(dāng)作副本集主節(jié)點(diǎn),10.43.159.58、10.43.159.60作為副本集副本節(jié)點(diǎn)。 2. 分別在每臺(tái)機(jī)器上建立MongoDB副本集測(cè)試文件夾 3. 下載安裝MongoDB的安裝程序包 4. 分別在每臺(tái)機(jī)器上啟動(dòng)MongoDB 給你的副本集取個(gè)名字吧,比如這里叫test: /data/MongoDBtest/MongoDB-linux-x86_64-2.4.8/bin/mongod --dbpath /data/MongoDBtest/replset/data --replSet test 從日志可以看出副本集還沒(méi)有初始化。 5. 初始化副本集 在三臺(tái)機(jī)器上任意一臺(tái)機(jī)器登陸MongoDB: /data/MongoDBtest/MongoDB-linux-x86_64-2.4.8/bin/mongo 使用admin數(shù)據(jù)庫(kù): use admin 定義副本集配置變量,這里的 _id:”test” 和上面命令參數(shù)“ –replSet test” 要保持一致: config = { _id:'test', members:[ 初始化副本集配置: rs.initiate(config); 輸出成功: { 'info' : 'Config now saved locally. Should come online in about a minute.', 'ok' : 1 } 查看日志,副本集啟動(dòng)成功后,56為主節(jié)點(diǎn)PRIMARY,58、60為副本節(jié)點(diǎn)SECONDARY,注意這里是三個(gè)節(jié)點(diǎn)共同選舉出的主節(jié)點(diǎn),有一定隨機(jī)性。 查看集群節(jié)點(diǎn)的狀態(tài): rs.status(); 整個(gè)副本集已經(jīng)搭建成功了。是不是超級(jí)簡(jiǎn)單? 副本集模式的MongoDB不僅搭建簡(jiǎn)單,而且功能強(qiáng)大?,F(xiàn)在回頭看看這種模式能否解決我們前面遺留的問(wèn)題:主節(jié)點(diǎn)掛了能否自動(dòng)切換連接? 先測(cè)試副本集數(shù)據(jù)復(fù)制功能是否正常 首先在主節(jié)點(diǎn)56上插入數(shù)據(jù),然后再副本節(jié)點(diǎn)上查看數(shù)據(jù),發(fā)現(xiàn)日志報(bào)錯(cuò): error: { '$err' : 'not master and slaveOk=false', 'code' : 13435 } at src/mongo/shell/query.js:128 這是因?yàn)槟J(rèn)只從主節(jié)點(diǎn)讀寫數(shù)據(jù),副本不允許讀,只要設(shè)置副本可以讀即可。在副本節(jié)點(diǎn)上執(zhí)行:rs.slaveOk(),然后查詢數(shù)據(jù),發(fā)現(xiàn)主節(jié)點(diǎn)的數(shù)據(jù)已經(jīng)同步過(guò)來(lái)了。 再測(cè)試下副本集的故障轉(zhuǎn)移功能 先停掉主節(jié)點(diǎn)56上的進(jìn)程,可以看到58和60節(jié)點(diǎn)上的日志顯示的就是投票過(guò)程。再執(zhí)行rs.status()可以看到集群狀態(tài)更新了,56為不可達(dá),58成為主節(jié)點(diǎn),60還是副本。再啟動(dòng)56節(jié)點(diǎn),發(fā)現(xiàn)還是58為主節(jié)點(diǎn),56變?yōu)楦北竟?jié)點(diǎn)。這樣就解決了第一個(gè)故障自動(dòng)轉(zhuǎn)移的問(wèn)題。 那么,對(duì)于主節(jié)點(diǎn)讀寫壓力過(guò)大,如何解決呢?常見(jiàn)的解決方案是讀寫分離,MongoDB副本集的讀寫分離如何做呢? 看圖說(shuō)話: 對(duì)于移動(dòng)APP的場(chǎng)景,通常寫操作遠(yuǎn)沒(méi)有讀操作多,所以一臺(tái)主節(jié)點(diǎn)負(fù)責(zé)寫,兩臺(tái)副本節(jié)點(diǎn)負(fù)責(zé)讀。從哪個(gè)節(jié)點(diǎn)讀,完全可以由客戶端選擇,數(shù)據(jù)讀取參數(shù)一共有五類(Primary、PrimaryPreferred、Secondary、SecondaryPreferred、Nearest):
典型的副本集組網(wǎng)中,除了有副本節(jié)點(diǎn),還有其他角色,比如仲裁節(jié)點(diǎn),如下圖: 其中的仲裁節(jié)點(diǎn)不存儲(chǔ)數(shù)據(jù),只是負(fù)責(zé)故障轉(zhuǎn)移的群體投票,這樣就少了數(shù)據(jù)復(fù)制的壓力。此外還有Secondary-Only、Hidden、Delayed、Non-Voting等角色。 Secondary-Only:不能成為Primary節(jié)點(diǎn),只能作為Secondary副本節(jié)點(diǎn),防止一些性能不高的節(jié)點(diǎn)成為主節(jié)點(diǎn)。 總結(jié)及思考 到此整個(gè)MongoDB副本集搞定了兩個(gè)問(wèn)題:
還有兩個(gè)問(wèn)題待后續(xù)解決:
這個(gè)可以通過(guò)MongoDB的分片功能來(lái)解決,我們下次再說(shuō)。Bye Bye! |
|