一:概念
相關概念及圖片引用自這里
mongodb副本集: 副本集是一組服務器,其中一個是主服務器,用於處理客戶請求;還有多個備份服務器,用於保存主服務器的數據副本。如果主服務器崩潰了,備份服務器自動將其中一個成員升級為新的主服務器。 由此可見副本集對於應對災難性事件是多么的合適。以前的mongo主從模式其實就是一個單副本的應用,沒有很好的擴展性和容錯性。而mongodb副本集具有多個副本保證了高性能,數據的一致性,容錯性,就算一個副本掛掉了還有很多副本存在,並且解決了上面第一個問題“主節點掛掉了,整個集群內會自動切換”。

由圖可以看到客戶端連接到整個副本集,不關心具體哪一台機器是否掛掉。主服務器負責整個副本集的讀寫,副本集定期同步數據備份,一但主節點掛掉,副本節點就會選舉一個新的主服務器,這一切對於應用服務器不需要關心。我們看一下主服務器掛掉后的架構:

副本集中的副本節點在主節點掛掉后通過心跳機制檢測到后,就會在集群內發起主節點的選舉機制,自動選舉一位新的主服務器。
其他關於選舉等詳細概念可以看這里。
官方推薦的副本集機器數量為至少3個,那我們也按照這個數量配置測試。
因此先准備3台虛擬機用於測試:
系統均為:Linux Debian ,分別為:

已分配好的可登錄用戶分別是:root,user1
二:安裝mongodb
以下記錄在安裝mongodb過程中遇到的問題:
1.在ip為84的虛擬機上,root用戶沒有開放遠程登錄權限,用root賬號登錄時報錯:Access denied (網上查到是因為sshd的設置不允許root用戶用密碼遠程登錄的原因)
解決辦法:user1用戶登錄后
su // 切換到管理員賬號
輸入 nano /etc/ssh/sshd_config 回車 //nano是用記事本打開,也可以使用 vi 打開
找到 # Authentication: LoginGraceTime 120 PermitRootLogin without passwd StrictModes yes
把“PermitRootLogin without passwd”改成“PermitRootLogin yes”
按“ctrl+o”保存再退出,退出后記得要重啟一下才生效!
reboot //重啟
2. root用戶目錄下安裝mongodb
root 登錄
cd /root //在root目錄下安裝
mkdir mongodb
拖動 mongodb-linux-x86_64-3.0.1.tgz 到mongodb目錄
解壓縮到當前目錄:tar zxvf mongodb-linux-x86_64-3.0.1.tgz
3. 配置mongodb啟動的配置文件 mongodb.conf

解釋一下參數名稱:
- dbpath: db數據文件存放位置
- logpath:db的日志文件存放位置
- logappend: 日志是否以追加方式寫入
- fork: 后台運行
- port: 訪問端口 //默認27017
- noauth: 無認證訪問(此處是為測試方便,請勿效仿)
- replSet:副本集核心參數,副本集的名稱,這個參數是必須的,而且必須三台機器完全一樣
- 更多參數可以根據需要添加
4. 設置環境變量
vi ~/.bashrc // ~/ 表示打開當前用戶目錄下面的.bashrc文件
拷貝以下設置到文件保存即可
export MONGOHOME=/root/mongodb/mongodb-linux-x86_64-3.0.1
export PATH=$MONGOHOME/bin:$PATH
5. 設置服務開機自啟動:
cd /etc/init.d //進入啟動項目文件夾下
touch mongodb 創建mongodb文件,將以下內容拷貝到文件並保存
#!/bin/sh
### BEGIN INIT INFO
# Provides: mongod
# Required-Start: $remote_fs $syslog
# Required-Stop: $remote_fs $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Start/stop
### END INIT INFO
# Source function library.
. /lib/lsb/init-functions
retval=0
pidfile=`ps -ef | grep 'mongod' | grep -v grep | awk '{print $2}'`
CONFIG="/root/mongodb/mongodb.conf"
PROGRAM="/root/mongodb/mongodb-linux-x86_64-3.0.1/bin/mongod"
MONGOPID=`ps -ef | grep 'mongod' | grep -v grep | awk '{print $2}'`
test -x $PROGRAM || exit 0
case "$1" in
start)
ulimit -n 3000
log_begin_msg "Starting MongoDB server"
$PROGRAM -f $CONFIG &
log_end_msg 0
;;
stop)
log_begin_msg "Stopping MongoDB server"
if [ ! -z "$MONGOPID" ]; then
kill -15 $MONGOPID
fi
log_end_msg 0
;;
status)
;;
*)
log_success_msg "Usage: /etc/init.d/mongodb {start|stop|status}"
exit 1
esac
exit 0
(在mongodb文件存在的情況下,可將mongodb的啟動文件拖動到 /etc/init.d文件夾下)
核對:啟動項目位置及配置文件位置
CONFIG="/root/mongodb/mongodb.conf"
PROGRAM="/root/mongodb/mongodb-linux-x86_64-3.0.1/bin/mongod"
MONGOPID=`ps -ef | grep 'mongod' | grep -v grep | awk '{print $2}'`
6. 配置好后reboot 重啟系統
檢測是否能進入mongo:
mongo -v 或者 mongo 命令。
注意項:
因為mongodb是安裝在root用戶下(Linux系統默認所安裝的軟件只能在當前用戶下有使用權限,換一個用戶就沒有權限訪問),當user用戶登錄后使用mongo命令時,會報錯沒有權限訪問,這是我們需要設置user用戶的訪問mongodb的權限。
1:user用戶登錄
在user用戶目錄下 加入環境變量,指向mongo安裝的文件夾:
vi ~/.bashrc 進入當前用戶下面的.bashrc文件
拷貝以下設置保存即可
export MONGOHOME=/root/mongodb/mongodb-linux-x86_64-3.0.1
export PATH=$MONGOHOME/bin:$PATH
2:mongodb的安裝目錄(root目錄)訪問權限
給mongodb的安裝目錄 :root目錄設置訪問權限(需要在root管理員用戶下設置) 在root當存目錄
cd /root
chmod 777 root (讀寫執行權限都有了)
chmod -R 777 root(文件的讀寫,創建文件夾等)
chmod a+x root 執行權限
設置完這兩部,在user賬號下,就能啟動mongodb了。
如果在啟動mongodb時報以下連接不上的mask錯誤,試試以下命令:
systemctl unmask mongodb
systemctl enable mongodb
systemctl start mongodb
3:在user用戶下,判斷開機啟動項下面的mongodb文件是否有執行權限
cd /etc/init.d/ 進入這個啟動項目錄
ls -al mongodb 查看mongodb啟動文件的權限 (./mongo) 按tab鍵不全 則是沒有執行權限
chmod a+x mongodb 給mongodb文件賦予執行權限 (需要在管理員權限下設置)
systemctl enable mongodb 對mongodb文件設置可用
systemctl start mongodb.service 啟動服務
4: 其他可能涉及的命令:
如果系統開放了防火牆,還需要開放防火牆的端口,可以使得3台機器相互之間能訪問,不會被牆掉。
列出INPUT 鏈所有的規則
iptables -L INPUT --line-numbers
#當然,自己不能被擋在外面,給自己開個后門
iptables -I INPUT -s 127.0.0.1 -p tcp --dport 27017 -j ACCEPT(出於業務邏輯的需要,有時還需要對服務器的公網IP授權)
iptables -I INPUT -s 172.16.9.241 -p tcp --dport 27017 -j ACCEPT
iptables -I INPUT -s 172.16.9.240 -p tcp --dport 27017 -j ACCEPT
iptables -I INPUT -s 172.16.9.85 -p tcp --dport 27017 -j ACCEPT
列出所有的服務,查看所有服務
systemctl list-units --type=service
df -h 查看磁盤空間
手動從配置文件啟動服務 :mongod -config ./mongodb-3.2.18/mongodb.conf(配置文件路徑)
三:設置副本集
在3個虛擬機上啟動mongo服務都沒有問題時,開始配置副本集。
隨便選擇某一台服務器做副本集初始化配置即可。
輸入mongo命令,啟動mongo 
config={ _id:"testrepl", members:[ {_id:0,host:"172.16.9.241:27017"}, {_id:1,host:"172.16.9.240:27017"}, {_id:2,host:"172.16.9.84:27017"}] } rs.initiate(config)
##########################
"_id": 副本集的名稱
"members": 副本集的服務器列表
"_id": 服務器的唯一ID
"host": 服務器主機
"priority": 是優先級,默認為1,優先級0為被動節點,不能成為活躍節點。優先級不位0則按照有大到小選出活躍節點。
"arbiterOnly": 仲裁節點,只參與投票,不接收數據,也不能成為活躍節點。
第一次初始化時報以下錯誤:
replSetInitiate quorum check failed because not all proposed set members responded affirmatively: 172.16.9.85:27017 failed with Failed attempt to connect to 172.16.9.85:27017; couldn't connect to server 172.16.9.85:27017 (172.16.9.85), connection attempt failed code:74
經查證發現root磁盤空間小了,副本集至少要求好幾G空間,以用來交互數據使用。重新分配虛擬機空間后解決問題。
若初始化成功,會返回以下代碼:
{
"ok" : 1
}
查看副本集狀態: rs.status() 命令

注意事項:
1.只需要選擇其中某一節點做初始化配置
2. 在副本集初始化的時候,一般都是copy不同的數據至各個結點,之后啟動結點,添加至集群,之后查詢狀態會發現是 STARTUP2,這是因為集群初始化在同步數據,同步完數據之后,狀態就變正常了
3. 在副本節點讀取數據報錯:
Error: error: { "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 }
因為241為主副本集,mongodb默認是從主節點讀寫數據的,而副本節點上不允許讀數據,因此在從服務器上需要做以下設置,需要設置副本節點可以讀。
repset:SECONDARY>db.getMongo().setSlaveOk(); 執行這句讓副本集可以讀
其實:有兩種方法實現從機的查詢:
第一種方法:db.getMongo().setSlaveOk();
第二種方法:rs.slaveOk();
上面兩行命令即允許此連接從副本讀取.
但是這種方式有一個缺點就是,下次再通過mongo進入實例的時候,查詢仍然會報錯,為此可以通過下列方式
vi ~/.mongorc.js
增加一行rs.slaveOk();
以后每次通過mongo命令進入都可以查詢了。
可以測試當主節點掛掉,副本節點就會選舉一個新的主服務器


當再次啟動241服務器的mongo時,會恢復其primary身份。
到這里,副本集就已經配置完成。
對於切換日志的操作,
>use admin
> db.runCommand({logRotate:1})
