MongoDB創建副本集
阿新 • • 發佈:2017-12-01
nosql mongodb 副本集CentOS6平臺安裝MongoDB3.2副本集
一,3臺機器全部安裝部署mongod
1,下載安裝包,並解壓tgz
curl -O https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-3.2.10.tgz
tar xf mongodb-linux-x86_64-3.2.10.tgz
mv mongodb-linux-x86_64-3.2.10 /usr/local/mongodb
2,,可執行文件添加到 PATH 路徑中:
export PATH=/usr/local/mongodb/bin:$PATH
echo 'export PATH=/usr/local/mongodb/bin:$PATH' > /etc/profile.d/mongodb.sh
3,關閉大頁面內存
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo "if test -f /sys/kernel/mm/transparent_hugepage/enabled;then
echo never > /sys/kernel/mm/transparent_hugepage/enabled
fi
if test -f /sys/kernel/mm/transparent_hugepage/defrag;then
echo never > /sys/kernel/mm/transparent_hugepage/defrag
fi" >> /etc/rc.d/rc.local
4,限制
ulimit -f unlimited
ulimit -t unlimited
ulimit -v unlimited
ulimit -n 64000
ulimit -m unlimited
ulimit -u 64000
5,創建數據庫目錄
mkdir -p /data0/mongodb/shardA/data
mkdir -p /data0/logs/mongodb/
6,運行MongoDB服務
(1)編寫配置文件
cat /data0/mongodb/shardA/mongo27017.conf
#mongodb shardA 27017
replSet=shardA
dbpath=/data0/mongodb/shardA/data
logpath=/data0/logs/mongodb/27017.log
#bind=192.168.9.168,127.0.0.1
port=27017
fork=true
maxConns=20000
logappend=true
smallfiles=true
(2)啟動
/usr/local/mongodb/bin/mongod -f /data0/mongodb/shardA/mongo27017.conf
#其他方式啟動
命令行指定dbpath和port
/usr/local/mongodb/bin/mongod --dbpath=/data0/mongodb/shardA --port 27017 &# 默認端口為27017
命令行指定dbpath和port,並啟動web界面
/usr/local/mongodb/bin/mongod --dbpath=/data0/mongodb/shardA --port 27017 --rest & #web默認端口為28017
7,查看是否啟動正常
netstat -lnptu | grep 27017
ps auxf | grep mongod | grep -v grep
MongoDB後臺管理shell
/usr/local/mongodb/bin/mongo 127.0.0.1:27017/test
/usr/local/mongodb/bin/mongo --port 27017
二,配置副本集
1,#連接一臺mongo
# /usr/local/mongodb/bin/mongo 192.168.9.168:27017
MongoDB shell version: 3.2.10
2,# 配置168為主,176為從,225為仲裁節點,priority最大為主節點,arbiterOnly僅作為仲裁
> cfg={_id:"shardA", members:[{_id:0,host:'192.168.9.168:27017',priority:2},{_id:1,host:'192.168.9.176:27017',priority:1},{_id:2,host:'192.168.9.225:27017',arbiterOnly:true}]};
{
"_id" : "shardA",
"members" : [
{
"_id" : 0,
"host" : "192.168.9.168:27017",
"priority" : 2
},
{
"_id" : 1,
"host" : "192.168.9.176:27017",
"priority" : 1
},
{
"_id" : 2,
"host" : "192.168.9.225:27017",
"arbiterOnly" : true
}
]
}
# 初始化
> rs.initiate(cfg)
{ "ok" : 1 }
# 也可以手動添加
> rs.initiate()
> rs.add("192.168.9.176:27017")
> rs.add("192.168.9.225:27017",{arbiterOnly:true})
{ "ok" : 1 }
# 刪除節點
> rs.remove()
3,查看狀態
#查看配置內容
> rs.conf()
#查看狀態信息
> rs.status()
#查看是否為主節點
> db.isMaster()
4,主節點插入數據
mongo 192.168.9.176:27017
> show dbs
> use Atest
> for (i=0;i<=1000;i++) db.coltest.insert({count:i})
> show tables
> db.coltest.count()
> db.coltest.find()
mongo 192.168.9.168:27017
> rs.slaveOk()
> show dbs
> show tables
> db.coltest.count()
> db.coltest.find()
shardA:SECONDARY> db.coltest.insert({"count":"10003"})
WriteResult({ "writeError" : { "code" : 10107, "errmsg" : "not master" } })
三,故障轉移測試
1,關閉主節點
mongo 192.168.9.176:27017
shardA:PRIMARY> use admin
switched to db admin
shardA:PRIMARY> db.shutdownServer()
server should be down...
2017-11-30T14:13:23.223+0800 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2017-11-30T14:13:24.116+0800 I NETWORK [thread1] Socket recv() errno:104 Connection reset by peer 127.0.0.1:27017
2017-11-30T14:13:24.116+0800 I NETWORK [thread1] SocketException: remote: (NONE):0 error: 9001 socket exception [RECV_ERROR] server [127.0.0.1:27017]
2017-11-30T14:13:24.116+0800 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) failed failed
2017-11-30T14:13:24.118+0800 I NETWORK [thread1] trying reconnect to 127.0.0.1:27017 (127.0.0.1) failed
2017-11-30T14:13:24.118+0800 W NETWORK [thread1] Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused
2017-11-30T14:13:24.118+0800 I NETWORK [thread1] reconnect 127.0.0.1:27017 (127.0.0.1) failed failed
>
2,查看備用節點會成為主節點
shardA:SECONDARY>
shardA:PRIMARY> rs.status()
{
"set" : "shardA",
"date" : ISODate("2017-11-30T06:13:57.404Z"),
"myState" : 1,
"term" : NumberLong(3),
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 0,
"name" : "192.168.9.168:27017",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 74322,
"optime" : {
"ts" : Timestamp(1512022413, 1),
"t" : NumberLong(3)
},
"optimeDate" : ISODate("2017-11-30T06:13:33Z"),
"infoMessage" : "could not find member to sync from",
"electionTime" : Timestamp(1512022412, 1),
"electionDate" : ISODate("2017-11-30T06:13:32Z"),
"configVersion" : 1,
"self" : true
},
{
"_id" : 1,
"name" : "192.168.9.176:27017",
"health" : 0,
"state" : 8,
"stateStr" : "(not reachable/healthy)",
"uptime" : 0,
"optime" : {
"ts" : Timestamp(0, 0),
"t" : NumberLong(-1)
},
"optimeDate" : ISODate("1970-01-01T00:00:00Z"),
"lastHeartbeat" : ISODate("2017-11-30T06:13:56.562Z"),
"lastHeartbeatRecv" : ISODate("2017-11-30T06:13:21.617Z"),
"pingMs" : NumberLong(0),
"lastHeartbeatMessage" : "Connection refused",
"configVersion" : -1
},
{
"_id" : 2,
"name" : "192.168.9.225:27017",
"health" : 1,
"state" : 7,
"stateStr" : "ARBITER",
"uptime" : 70496,
"lastHeartbeat" : ISODate("2017-11-30T06:13:56.543Z"),
"lastHeartbeatRecv" : ISODate("2017-11-30T06:13:52.776Z"),
"pingMs" : NumberLong(0),
"configVersion" : 1
}
],
"ok" : 1
}
shardA:PRIMARY>
3,重新啟動原主節點,現主節點還會切過去
shardA:SECONDARY> db.isMaster()
{
"hosts" : [
"192.168.9.168:27017",
"192.168.9.176:27017"
],
"arbiters" : [
"192.168.9.225:27017"
],
"setName" : "shardA",
"setVersion" : 1,
"ismaster" : false,
"secondary" : true,
"primary" : "192.168.9.176:27017",
"me" : "192.168.9.168:27017",
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : ISODate("2017-11-30T06:20:47.355Z"),
"maxWireVersion" : 4,
"minWireVersion" : 0,
"ok" : 1
}
4,關閉副本集
五,維護相關
1,先關閉從節點、仲裁節點。或者先關閉仲裁節點,最後關閉從節點。則:主節點自動變為從節點
2,先關閉主節點,則從節點自動變為主節點,在仲裁節點關閉之前,新主節點不能關閉
初始化的時候主備節點受priority的影響
priority: 是優先級,默認為1,優先級0為被動節點,不能成為活躍節點。優先級不為0則按照由大到小選出活躍節點。
rs輔助函數
> rs.help()
rs.status() { replSetGetStatus : 1 } checks repl set status
rs.initiate() { replSetInitiate : null } initiates set with default settings
rs.initiate(cfg) { replSetInitiate : cfg } initiates set with configuration cfg
rs.conf() get the current configuration object from local.system.replset
rs.reconfig(cfg) updates the configuration of a running replica set with cfg (disconnects)
rs.add(hostportstr) add a new member to the set with default attributes (disconnects)
rs.add(membercfgobj) add a new member to the set with extra attributes (disconnects)
rs.addArb(hostportstr) add a new member which is arbiterOnly:true (disconnects)
rs.stepDown([stepdownSecs, catchUpSecs]) step down as primary (disconnects)
rs.syncFrom(hostportstr) make a secondary sync from the given member
rs.freeze(secs) make a node ineligible to become primary for the time specified
rs.remove(hostportstr) remove a host from the replica set (disconnects)
rs.slaveOk() allow queries on secondary nodes
rs.printReplicationInfo() check oplog size and time range
rs.printSlaveReplicationInfo() check replica set members and replication lag
db.isMaster() check who is primary
reconfiguration helpers disconnect from the database so the shell will display
an error, even if the command succeeds.
六,設計副本集
1,副本集重要的一個概念是"大多數",大多數為一半以上的成員
比如5個成員的副本集,有3個為網絡不可達,仍有二個可以正常工作,但達不到大多數的要求,所以無法選出主節點,如果 有個是主節點,會切換為備節點;
主要防止,3個網絡不可達,為3個可通信,防止出現2個主節點;
2,推薦模式有:
一個數據中心奇數成員
倆個數據中心奇數成員,將大多數放在一個數據中心
三個數據中心,倆個相等數量成員的數據中心,一個為決定主節點的數據中心
3,選舉機制
當一個備份節點無法與主節點連通時,它會聯系並請求其他的副本集成員將自己選舉為自己。
其它成員會做幾項理性的檢查:
(1)自身是否能夠與主節點通信
(2)希望被選舉為主節點的備份節點的數據是否為最新
(3)有沒有其他更高優先級的成員可以被選舉為主節點
七,成員配置項
1,選舉仲裁者
只參與選舉,並不保存數據
(1)最多只能有一個仲裁者
(2)如果節點數為奇數,則不需要仲裁者
# 添加仲裁成員
rs.addArb("192.168.9.168:27017")
rs.add({_id:2,host:'192.168.9.225:27017',arbiterOnly:true})
2,優先級
優先級取值範圍0-100,默認為1,0為永遠不可以成為主節點,這樣的稱為被動成員
優先級越高,且擁有最新的數據,那麽會被選舉為主節點
3,隱藏成員
客戶端不會向隱藏成員發送請求,隱藏成員也不會作為復制源
hidden:true 只有優先級0的成員 才能被隱藏
4,延遲備份節點
八,同步
復制用於多臺服務器之間的備份數據。使用操作日誌oplog實現的。
oplog是主節點local數據庫中一個固定集合,備份節點通過查詢這個集合就可以知道需要進行復制的操作
1,初始化同步
(1)成員會做一些記錄前的準備工作:選擇一個成員作為同步源,在local.me中為自己創建一個標識符,刪除所有已存在的數據庫,重新同步
(2)克隆,將同步源的所有記錄全部復制到本地
(3)進入oplog同步的第一步,克隆中的所有操作都會被記錄到oplog中
(4)oplog同步的第二步,用於將第一個oplog同步中的操作記錄下來
(5)本地數據應該與主節點在某個時間點的數據集完全一致了,可以創建索引
(6)當前節點的數據如果仍落後於同步源,那麽oplog同步過程的最後一步就是將創建索引期間的所有操作全部同步過來,防止該成員成為備份節點
(7)當前成員完成初始化同步,切換到普通同步狀態
九,心跳
成員每隔2s會向其他成員發送一個心跳請求
成員狀態:
1,STARTUP
成員剛啟動時處於這個狀態。mongodb會嘗試加載成員的副本集配置。加載成功後,會進入STARTUP2
2,STARTUP2
整個初始化同步過程 都處於這個狀態
3,RECOVERING
4,ARBITER
5,DOWN
6,UNKNOWN
7,REMOVED
8,ROLLBACK
9,FATAL
十,管理
1,以單機模式啟動成員
(1)查看命令行參數
> db.serverCmdLineOpts()
(1)如果要對這臺服務器維護,可以重啟;重啟時不適用 replSet選項。這樣會成為一個單機的mongod,可以進行讀和寫
(2)可以改變監聽端口,dbpath值不變
(3)維護完後,以最原始的參數重新啟動後會自動與副本集的其他成員進行同步。
2,副本集配置
(1)創建副本集
# 配置168為主,176為從,225為仲裁節點,priority最大為主節點,arbiterOnly僅作為仲裁
> cfg={_id:"shardA", members:[{_id:0,host:'192.168.9.168:27017',priority:2},{_id:1,host:'192.168.9.176:27017',priority:1},{_id:2,host:'192.168.9.225:27017',arbiterOnly:true}]};
# 初始化
> rs.initiate(cfg)
(2)修改副本集成員
a)增加成員
rs.add("192.168.9.169:27017")
文檔形式添加指定復雜的配置
rs.add({_id:4,host:'192.168.9.169:27017',priority:1})
b)移除成員
rs.remove("192.168.9.169:27017")
c)通過rs.config修改
> var config = rs.config()
> config.members[0].host = "192.168.9.179:27017"
> rs.reconfig(config)
註意點:
不能修改成員的_id字段
不能將接收rs.reconfig命令的成員的優先級設為0
不能將仲裁成員變為非仲裁成員
不能將"buildIndexes":false的成員修改為"buildIndexes":true
3,創建比較大的副本集
副本集的最多只能擁有12個成員,其中只有7個成員擁有投票權
如果要創建7個以上成員的副本集,只有7個成員可以擁有投票權,需要其他成員的投票數量設置為0
> rs.add({"_id":7,"host":server-7:27017,"votes":0})
4,修改成員狀態
# 主節點變為備節點
# 默認為60s
> rs.stepDown(time)
# 阻止選舉,始終處於備節點
> rs.freeze(time)
# 強制進入維護模式
> db.adminCommand({"replSetMaintenance":true})
# 退出進入維護模式
> db.adminCommand({"replSetMaintenance":false})
5,狀態
# 查看同步狀態
> db.printSlaveReplicationInfo()
# 查看同步源
> db.adminCommand({"replSetGetStatus":1}).syncingTo
192.168.9.176:27017
# 指定復制源
> secondary.adminCommand({"replSetSyncFrom":"server0:27017"})
# 禁用復制鏈
# 復制延遲查看
# 主節點上
> db.printReplicationInfo()
# 備節點上
> db.printSlaveReplicationInfo()
報錯:
shardA:SECONDARY> show dbs
2017-11-30T13:57:10.376+0800 E QUERY [thread1] Error: listDatabases failed:{ "ok" : 0, "errmsg" : "not master and slaveOk=false", "code" : 13435 } :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
Mongo.prototype.getDBs@src/mongo/shell/mongo.js:62:1
shellHelper.show@src/mongo/shell/utils.js:761:19
shellHelper@src/mongo/shell/utils.js:651:15
@(shellhelp2):1:1
原因:為了保護應用程序,以免意外連接到備節點,讀取到過期數據。備份節點默認會拒絕請求。
解決:設置從備份節點讀取數據沒有問題.salveOk是對連接設置的,不是對數據庫設置的。。
> rs.slaveOk()
MongoDB創建副本集