在任何服務系統(tǒng)中,要提供系統(tǒng)服務高可用,必須要解決單點故障及實現(xiàn)故障自動轉(zhuǎn)移。mongodb的副本集提供了這樣的功能,副本集由多個mongodb實例組成,其中一個為主,其他為從,解決了單點故障。另外主實例無法服務時,mongodb會重新選舉主實例進行故障轉(zhuǎn)移。
一、mongodb實例啟動準備
下載解壓
cd /usr/local
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.4.6.tgz
tar -xvf mongodb-linux-x86_64-3.4.6.tgz
mv mongodb-linux-x86_64-3.4.6 mongodb
設置環(huán)境
vim /etc/profile
export MONGODB_HOME=/usr/local/mongodb
export PATH=$MONGODB/bin:$PATH
source /etc/profile
由于這里搭建mongodb副本集,所以至少需要三個mongodb實例,兩個數(shù)據(jù)實例,一個仲裁實例,首先創(chuàng)建三個數(shù)據(jù)目錄
mkdir -p /data/mongodb1
mkdir -p /data/mongodb1/{log,conf}
touch /data/mongodb1/log/mongodb.log
mkdir -p /data/mongodb2
mkdir -p /data/mongodb2/{log,conf}
touch /data/mongodb2/log/mongodb.log
mkdir -p /data/mongodb3
mkdir -p /data/mongodb3/{log,conf}
touch /data/mongodb3/log/mongodb.log
創(chuàng)建配置文件,配置文件放在/data/mongodb1/conf/目錄下,文件名為mongodb.conf,配置如下:
dbpath=/data/mongodb1
logpath=/data/mongodb1/log/mongodb.log
logappend=true
noprealloc=true
port=27011
fork=true
replSet=test
其他兩個實例配置文件內(nèi)容和位置一樣,修改目錄和端口就可以了,其他兩個實例端口分別為:27012、27013。其中,replSet參數(shù)表示副本集名,三個實例必須配置一致。
二、啟動實例
執(zhí)行下面命令啟動三個實例
mongod -f /data/mongodb1/conf/mongodb.conf
mongod -f /data/mongodb2/conf/mongodb.conf
mongod -f /data/mongodb3/conf/mongodb.conf
三個實例啟動成功后,不代表副本集已經(jīng)搭建成功了,還需要進行副本集初始化。
三、初始化副本集
連接任何一個實例進行初始化
mongo --port 27011
use admin
config={
_id:'test',
members:[
{_id:1, host:'localhost:27011',priority:2},
{_id:2, host:'localhost:27012',priority:1},
{_id:3, host:'localhost:27013',arbiterOnly:true}
]
}
rs.initiate(config)
上面執(zhí)行成功后,可以使用rs.status()查看副本集當前狀態(tài)。
上面配置文件中,_id:'test'表示副本集名稱,與前面mongodb.conf配置文件中的replSet參數(shù)配置的名稱要一致。
priority:2表示優(yōu)先級,優(yōu)先級越高,副本集初始化時會選舉為主。arbiterOnly:true表示該實例為仲裁節(jié)點,不存儲數(shù)據(jù),只參與投票。
四、創(chuàng)建管理員用戶和讀寫用戶
連接到主實例,創(chuàng)建用戶
mongo --port 27011
use admin
db.createUser({
user:'dba',
pwd:'dba',
roles:[{role:"userAdminAnyDatabase", db:"admin"}, {role:"readWriteAnyDatabase", db:"admin"}]
})
db.createUser({
user:'rd',
pwd:'rd',
roles:[{role:'readWrite', db:'test'}]
})
創(chuàng)建好后,可以使用show users查看所有創(chuàng)建的用戶信息
五、為副本集增加權(quán)限認證
副本集采用keyfile文件來實現(xiàn)權(quán)限認證,并且副本集中的所有成員使用的keyfile必須一樣。
# 生成keyfile文件
openssl rand -base64 90 > /data/mongodb1/conf/keyfile
cp /data/mongodb1/conf/keyfile /data/mongodb2/conf/keyfile
cp /data/mongodb1/conf/keyfile /data/mongodb3/conf/keyfile
另外需要注意,keyfile文件權(quán)限必須是X00,也就是說,不能給group和other成員分配任何權(quán)限,否則實例無法啟動。
chmod 400 /data/mongodb1/conf/keyfile
chmod 400 /data/mongodb2/conf/keyfile
chmod 400 /data/mongodb3/conf/keyfile
生成好keyfile之后,將keyfile寫入mongodb.conf配置文件中,在mongodb.conf配置文件中增加如下配置:
keyFile=/data/mongodb1/conf/keyfile
其他實例做同樣修改,重啟所有實例。
在配置文件中開啟了keyFile,就不需要開啟auth認證,因為開啟keyFile,就默認開啟了auth。
六、驗證
連接主實例
mongo --port 27011

發(fā)現(xiàn)沒有權(quán)限執(zhí)行,使用db.auth('dba', 'dba')進行權(quán)限認證,再次執(zhí)行就可以查看了。

創(chuàng)建一個數(shù)據(jù)庫test,然后寫入一些數(shù)據(jù)。

退出客戶端重新連接,不認證無法進行數(shù)據(jù)庫讀寫操作。

下面使用前面創(chuàng)建的rd讀寫用戶來認證,發(fā)現(xiàn)認證失敗。這是因為,rd用戶是在admin庫下面創(chuàng)建,所以必須要到admin庫下面認證,mongodb下的用戶是隨著庫走的。

下面連接到從實例上面,雖然用戶已經(jīng)認證可以了,但無法查看數(shù)據(jù)。

這是因為mongodb默認是從主節(jié)點讀寫數(shù)據(jù)的,副本節(jié)點上不允許讀(更不能寫入),但可以設置副本節(jié)點可以讀,使用db.getMongo().setSlaveOk()命令就可以了。

七、PHP實現(xiàn)
首先連接主實例,在test庫下面創(chuàng)建一個讀寫用戶
# 登錄管理員權(quán)限
use admin
db.auth('dba', 'dba')
# 切換到test庫下創(chuàng)建用戶
use test
db.createUser({
user:'test',
pwd:'test',
roles:[{role:'readWrite', db:'test'}]
})

php代碼如下:
<?php
$m = new MongoClient(
"mongodb://test:test@192.168.99.100:27012,192.168.99.100:27011/test",
array(
'connectTimeoutMS' => 100,
'readPreference' => MongoClient::RP_PRIMARY_PREFERRED,
)
);
$db = $m->test;
$collection = $db->person;
$collection->insert(array(
'name' => 'li',
'age' => 22,
));
$cursor = $collection->find();
foreach ($cursor as $document) {
var_dump($document);
}
執(zhí)行結(jié)果

最后,副本集的故障轉(zhuǎn)移可以自行驗證下。