Replica Set功能
1, Replica Set是指一組服務器的集群膏燃,其中有一個主服務器,用于處理用戶的請求;其余為備份服務器,用于保存主服務的數(shù)據(jù)副本莺掠。如果主服務器崩潰了极谊,會自動將一個備份服務器升級為新的主服務器吐限,從而保證服務器的進行澡为。
2,MongoDB提供復制的功能摸屠,用來將數(shù)據(jù)保存到多臺服務器上谓罗,在實際生產(chǎn)環(huán)境中,強烈建議集群并使用復制的功能季二,以實現(xiàn)故障轉(zhuǎn)移和健壯服務器檩咱。
創(chuàng)建副本集
包含以下步驟:
1揭措,在mongodb 文件夾下創(chuàng)建dbs文件夾,在dbs文件夾下面創(chuàng)建 db1 db2 db3 三個文件夾來存放數(shù)據(jù)刻蚯。
在mongodb 文件夾下創(chuàng)建logs文件夾,在logs文件夾西面創(chuàng)建文件 log1 log2 log3 三個文件用來存放日志绊含。2, 在啟動MongoDB服務器的時候,使用 “--replSet 副本集名稱” 選項 啟動mongod
./mongod --dbpath ../dbs/db1 --logpath ../logs/log1 --port 20001 --fork --replSet myrep
./mongod --dbpath ../dbs/db2 --logpath ../logs/log2 --port 20002 --fork --replSet myrep
./mongod --dbpath ../dbs/db3 --logpath ../logs/log3 --port 20003 --fork --replSet myrep
- 3, 副本集進行初始化
./mongo 127.0.0.1:20001
rs.initiate({_id:"rep",members:[
{_id:0,host:'127.0.0.1:20001'},
{_id:1,host:'127.0.0.1:20002'},
{_id:2,host:'127.0.0.1:20003}
]
})
以上就可以創(chuàng)建出副本集(Replica Set)
副本集(Replica Set)成員
1炊汹,Primary 主節(jié)點
接收所有的讀寫操作躬充。2,Secondaries 副節(jié)點
主要從Primar(主節(jié)點) 復制數(shù)據(jù)讨便,不接收寫操作3,Arbiter 仲裁者
只負責選舉不報錯數(shù)據(jù) 充甚,不接收客戶端的讀寫操作
示意圖
- 1,在以下三個成員副本集中霸褒,Primary接受所有寫入操作津坑。 然后,Secondaries復制oplog以應用于其數(shù)據(jù)集傲霸。
- 2,以下三個成員副本集有兩個副成員眉反。 副節(jié)點復制主節(jié)點的oplog并將操作應用于其數(shù)據(jù)集昙啄。
-
3,以下三個成員副本集有一個副節(jié)點寸五,一個主節(jié)點梳凛,一個仲裁者,仲裁者只是起到選擇主節(jié)點的作用梳杏,不存儲數(shù)據(jù)
- 4韧拒,當主節(jié)點掛掉后,副節(jié)點會有10秒的時間選舉出副節(jié)點升級為主節(jié)點十性,有很強的容錯能力叛溢。
查看副本集(Replica Set)狀態(tài)
rs是輔助函數(shù),其中包含了與復制相關的輔助函數(shù)劲适,可以通過rs.help() 查看楷掉。
rs.help()
函數(shù) | 描述 |
---|---|
rs.status() | 查看副本集狀態(tài) |
rs.initiate(cfg) | 副本集進行初始化 |
rs.conf() | local.system.replset 中獲取配置信息 |
rs.reconfig(cfg) | 更新副本集配置 |
rs.add(hostportstr) | 添加一個成員 |
rs.addArb(hostportstr) | 添加一個選舉者 arbiterOnly:true |
rs.stepDown([stepdownSecs, catchUpSecs]) | 主服務器變?yōu)閭浞莘掌?/td> |
rs.syncFrom(hostportstr) | 備份服務器指定hostportstr中同步數(shù)據(jù) |
rs.freeze(secs) | 使不能成為主節(jié)點的節(jié)點可以成為主節(jié)點 |
rs.remove(hostportstr) | 從副本集刪除一個節(jié)點 |
rs.slaveOk() | 允許副節(jié)點查詢數(shù)據(jù) |
rs.printReplicationInfo() | 查看oplog 的大小時間 |
rs.printSlaveReplicationInfo() | 查看副本集成員同步情況 |
db.isMaster() | 查看是否為主節(jié)點 |
rs.status()說明
rs.status()
{
"set" : "myrep",
"date" : ISODate("2017-08-17T09:12:34.724Z"),
"myState" : 1,
"term" : NumberLong(181),
"heartbeatIntervalMillis" : NumberLong(2000),
"members" : [
{
"_id" : 0,
"name" : "127.0.0.1:20001",
"health" : 1,
"state" : 1,
"stateStr" : "PRIMARY",
"uptime" : 20690,
"optime" : {
"ts" : Timestamp(1502950202, 10),
"t" : NumberLong(181)
},
"optimeDate" : ISODate("2017-08-17T06:10:02Z"),
"electionTime" : Timestamp(1502940488, 1),
"electionDate" : ISODate("2017-08-17T03:28:08Z"),
"configVersion" : 2,
"self" : true
},
{
"_id" : 1,
"name" : "127.0.0.1:20002",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 20671,
"optime" : {
"ts" : Timestamp(1502950202, 10),
"t" : NumberLong(181)
},
"optimeDate" : ISODate("2017-08-17T06:10:02Z"),
"lastHeartbeat" : ISODate("2017-08-17T09:12:33.315Z"),
"lastHeartbeatRecv" : ISODate("2017-08-17T09:12:33.315Z"),
"pingMs" : NumberLong(37),
"syncingTo" : "127.0.0.1:20001",
"configVersion" : 2
},
{
"_id" : 2,
"name" : "127.0.0.1:20003",
"health" : 1,
"state" : 2,
"stateStr" : "SECONDARY",
"uptime" : 20651,
"optime" : {
"ts" : Timestamp(1502950202, 10),
"t" : NumberLong(181)
},
"optimeDate" : ISODate("2017-08-17T06:10:02Z"),
"lastHeartbeat" : ISODate("2017-08-17T09:12:33.315Z"),
"lastHeartbeatRecv" : ISODate("2017-08-17T09:12:33.314Z"),
"pingMs" : NumberLong(37),
"syncingTo" : "127.0.0.1:20001",
"configVersion" : 2
}
],
"ok" : 1
}
1, self:這個字段只會出現(xiàn)在運行rs.status函數(shù)的成員信息中。
2, stateStr: 服務器狀態(tài)PRIMARY霞势,SECONDARY烹植,ARBITER。
3, uptime: 從成員可達一直到現(xiàn)在所經(jīng)歷的時間愕贡,單位是秒草雕。
4,optimeDate: 每個成員的oplog中最后一個操作發(fā)生的時間固以。
注意:這里的狀態(tài)是每個成員通過心跳報告上來的狀態(tài),所以optime跟實際時間可能會有 幾秒鐘的偏差墩虹。5,lastHeartbeat:當前服務器最后一次收到其他成員心跳的時間,如果網(wǎng)絡故障,
或者是當前服務器比較繁忙,這個時間可能會是2秒鐘之前。6败晴,pingMs:心跳從當前服務器到達某個成員所花費的平均時間浓冒。
7,errmsg:成員在心跳請求中返回的狀態(tài)信息,通常是一些狀態(tài)信息,而不是錯誤信息尖坤。
8稳懒,state:也表示服務器的狀態(tài),state是內(nèi)部表示,而stateStr是適合閱讀的表示。
9慢味,optime:和optimeDate也是一樣的,只是optimeDate更適合閱讀场梆。
10,syncingTo:表示當前成員正在從哪個成員處進行復制纯路。
修改副本集配置
- 1或油,從副本集中刪除成員
rs.remove("ip:port")
rs.remove("127.0.0.1:20003")
- 2,為副本集添加成員
rs.add(“ip:port”);
rs.add("127.0.0.1:20003")
副本集中主節(jié)點的確認
是通過選舉機制驰唬,要大多數(shù)節(jié)點同意的節(jié)點才能成為主節(jié)點顶岸。
成員配置選項——選舉仲裁者
所謂仲裁者,就是不保存數(shù)據(jù)叫编,專門用來投票選舉主節(jié)點的副本辖佣,以解決副本個數(shù)為偶數(shù)的情況。
1搓逾,啟動仲裁者和普通的副本方式一樣卷谈。
2, 只是配置該節(jié)點的時候霞篡,設置:arbiterOnly:true ,如果用rs來加入的話應該是:rs.addArb("ip:port")
rs.initiate({_id:"rep",members:[
{_id:0,host:'127.0.0.1:20001'},
{_id:1,host:'127.0.0.1:20002'},
{_id:2,host:'127.0.0.1:20003,arbiterOnly:true }
]
})
3,最多只能有一個仲裁者世蔗。
4,盡量使用奇數(shù)個成員朗兵,而不是采用仲裁者
成員配置選項priority——優(yōu)先級
優(yōu)先級用來表示一個成員渴望成為主節(jié)點的程度污淋,可以在0-100之間,默認是1.
查看priority
rs.config()
{
"_id" : "myrep",
"version" : 4,
"protocolVersion" : NumberLong(1),
"members" : [
{
"_id" : 0,
"host" : "127.0.0.1:20001",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "127.0.0.1:20002",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : true,
"priority" : 0,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "127.0.0.1:20003",
"arbiterOnly" : true,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
}
}
}
- 1:如果優(yōu)先級為0的話,表示這個成員永遠不能夠成為主節(jié)點余掖。
2:擁有最高優(yōu)先級的成員會優(yōu)先選舉為主節(jié)點,只要它能得到“大多數(shù)”的票,并且數(shù)據(jù)是
最新的,就可以了芙沥。3:如果一個高優(yōu)先級的成員,數(shù)據(jù)又是最新的,通常會使得當前的主節(jié)點自動退位,讓這個
優(yōu)先級高的做主節(jié)點。
成員配置選項hidden——隱藏成員
對于設置為隱藏的成員浊吏,客戶端不能發(fā)送請求而昨,也不會作為復制源,通常用來做備份服務器找田,
1:在配置這個節(jié)點的時候歌憨,設置hidden:true
2: 只有優(yōu)先級為0的成員才能被隱藏。
3:可以通過rs.config()或者rs.status()查看到
var config = rs.config();
config.members[1].hidden=true;
config.members[1].priority=0;
rs.reconfig(config);
查看配置
rs.config()
成員配置選項slaveDelay——延遲備份節(jié)點
可以通過slaveDelay設置一個延遲的備份節(jié)點墩衙,以在主節(jié)點的數(shù)據(jù)不小心被破壞后务嫡,能從備份中恢復回來甲抖。要求該備份節(jié)點的優(yōu)先級為0.
var config = rs.config();
config.members[1].hidden=true;
config.members[1].priority=0;
config.members[1].slaveDelay=1000; 秒
rs.reconfig(config);
查看配置
rs.config()
成員配置選項buildIndexes——創(chuàng)建索引
如果不需要備份節(jié)點與主節(jié)點擁有一樣的索引,可以設置:buildIndexes:false。
1:這是一個永久選項,一旦指定了,就無法恢復為創(chuàng)建索引的正常的節(jié)點了心铃。
2:如果要恢復,只能刪掉,重新再創(chuàng)建節(jié)點了准谚。
3:同樣要求該節(jié)點的優(yōu)先級為0。
var config = rs.config();
config.members[1].priority=0;
config.members[1].buildIndexes=false;
rs.reconfig(config);
查看配置
rs.config()
操作日志oplog
Oplog 是主節(jié)點的local 數(shù)據(jù)庫中的一個固定集合去扣,按順序記錄了主節(jié)點的每一次寫操作柱衔,
MongoDB 的復制功能是使用oplog來實現(xiàn)的,備份節(jié)點通過查詢這個集合就可以知道需要進行
哪些數(shù)據(jù)的復制了愉棱。
每個備份節(jié)點也都維護著自己的oplog,記錄著每次從主節(jié)點復制數(shù)據(jù)的操作唆铐。這樣 每個節(jié)點都可以作為數(shù)據(jù)的同步源提供給其他成員使用。
注意事項
1:由于是先復制數(shù)據(jù),再寫日志,因此可能會出現(xiàn)重復的復制操作,這個沒有關系,MongoDB會處理這種情況,多次執(zhí)行Oplog中同一個操作與執(zhí)行一次是一樣的奔滑。
2:oplog的大小是固定的,它只能保存特定數(shù)量的操作日志,如果多次大批量的執(zhí)行操作,oplog很快就會被填滿,oplog的大小,可以通過mongod的--plogSize來指定艾岂。
- 3:oplog的內(nèi)容,在local數(shù)據(jù)庫的oplog.rs集合里面
查看oplog.rs集合
use local
db.oplog.rs.find().limit(2)
{ "ts" : Timestamp(1502377323, 1), "h" : NumberLong("-5133493683417483983"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "initiating set" } }
{ "ts" : Timestamp(1502377334, 1), "t" : NumberLong(1), "h" : NumberLong("-1049014418502032537"), "v" : 2, "op" : "n", "ns" : "", "o" : { "msg" : "new primary" } }
初始化同步
當副本集的一個成員啟動的時候,他就會檢查自身狀態(tài)朋其,然后到集群中檢查是否需要同步王浴,
以及從哪兒同步,并進行數(shù)據(jù)的復制梅猿,這個過程就稱為初始化同步叼耙。
初始化要經(jīng)歷以下步驟:
1,記錄前的準備工作:選擇一個成員作為同步源粒没,在local.me 中為自己創(chuàng)建一個標識符,刪除所有已存在的數(shù)據(jù)庫簇爆,以全新的狀態(tài)開始同步癞松。
2,從數(shù)據(jù)源把所有數(shù)據(jù)復制到本地 入蛆。
3响蓉,寫oplog,把所有復制中的操作寫入oplog。
4哨毁,把上一步oplog同步中的操作寫入oplog
5,此時數(shù)據(jù)應該和數(shù)據(jù)源一致了枫甲,可以開始創(chuàng)建索引了。
6扼褪,如果當前節(jié)點的數(shù)據(jù)仍然遠遠落后于數(shù)據(jù)源想幻,那么oplog會將創(chuàng)建索引間的所有操作同步過來。
7话浇,完成初始化同步后脏毯,切換到普通同步狀態(tài),也就可以作為備份節(jié)點使用了幔崖。
處理陳舊數(shù)據(jù)
如果備份節(jié)點遠遠落后于同步源的數(shù)據(jù),那么這個節(jié)點上的數(shù)據(jù)就是成舊數(shù)據(jù)食店。
通常的處理辦法是:讓主節(jié)點使用比較大的oplog,以保存足夠多的操作日志,可以讓備份節(jié)點慢慢來同步操作渣淤。
心跳
為了維護集合的最新狀態(tài),每個成員每個2秒會向其他成員發(fā)送一個心跳請求吉嫩,用于檢查每個成員的狀態(tài)价认。
常見狀態(tài):
1:主節(jié)點、備份節(jié)點
2:STARTUP:成員剛啟動時處于這個狀態(tài),加載完副本集配置后,進入STARTUP2
3:STARTUP2:整個初始化同步過程都處于這個狀態(tài)
4:RECOVERING:表明成員運轉(zhuǎn)正常,但暫時還不能處理讀取請求
5:ARBITER:仲裁者始終處于這個狀態(tài)
系統(tǒng)出現(xiàn)故障時的狀態(tài):
1:DOWN:成員不可到達,有可能成員還是在正常運行,也有可能掛了
2:UNKNOWN:標識一個成員無法到達其他所有的成員
3:REMOVED:成員被移出副本集
4:ROLLBACK:成員正在進行數(shù)據(jù)回滾
5:FATAL:成員出現(xiàn)了致命的錯誤,也不再嘗試恢復正常
回滾
回滾的時候自娩,會把受到影響的文檔用踩,保存到數(shù)據(jù)目錄下的rollback目錄中,文件名為
集合名稱.bson椒功。
<database>.<collection>.<timestamp>.bson
records.accounts.2011-05-09T18-10-04.0.bson
基本步驟:
1捶箱,判斷是否需要回滾,典型就是副本記錄和主記錄不一致了动漾。
2丁屎,在兩個oplog 中尋找最后一個共同點
3,然后副本回滾到這個共同點
4旱眯,副本再從主節(jié)點同步數(shù)據(jù)回來
注意
如果要回滾的數(shù)據(jù)很多晨川,比如大于300M,或者需要操作30分鐘以上,回滾就會失敗删豺,如果回滾失敗的話共虑,就需要重新同步了。
以單機模式啟動成員
由于很多維護的工作需要寫入操作,所以不合適在副本集中操作,可以以單機模式
啟動成員,也就是不要使用副本的選項,就跟以前啟動單獨的服務器一樣呀页。一般使用一個 跟副本集配置中不一樣的端口號,這樣其他成員會認為這個服務器掛了妈拌。
副本集的配置
副本集的配置以一個文檔的形式保存在local庫中system.replSet 集合中,副本集所有成員的這個文檔都是相同的蓬蝶。絕對不要使用update來更新這個文檔尘分,應該使用rs或者replSetReconfig命令來修改副本集的配置。
先rs.config()得到當前配置,然后修改數(shù)據(jù),再rs.reconfig 即可丸氛。但有如下限制:
1: 不能修改成員的"_id"字段培愁。
2: 不能接收rs.reconfig命令的成員的優(yōu)先級設置為0。
3: 不能將仲裁者變成正常成員缓窜,反之也不行定续。
4: 不能將buiildIndex為false的成員修改為true
創(chuàng)建比較多的副本集
副本集最多只能擁有12個成員,只有7個成員擁有投票權禾锤。因此要創(chuàng)建超過7個副本集的話私股,需要將其他成員的投票權設置為0:
rs.add({“_id”:8,”host”:”localhost:20008”,”votes”:0});
如果要配置超過12個成員的話,需要使用Master/Slave的方式,不過這個方式已經(jīng) 不建議使用了,如果將來副本集能支持更多成員的話,這個方式可能會立即廢除。
強制重新配置
如果副本集無法達到“大多數(shù)”要求的話恩掷,可能會無法選出主節(jié)點庇茫,這個時候,可以shell連接任意
一個成員螃成,然后使用force 選項強制重新配置旦签,如下
rs.reconfig(config,{“force”:true});
把主節(jié)點變?yōu)閭浞莨?jié)點
可以使用stepDown函數(shù),可以自己指定退化的持續(xù)時間,
rs.stepDown(); 或者 rs.stepDown(60); //秒為單位
阻止選舉
如果對主節(jié)點進行維護查坪,但不希望這段時間其他節(jié)點選舉新的主節(jié)點,可以在每個備份節(jié)點上
執(zhí)行freeze命令宁炫,強制他們始終處于備份狀態(tài)偿曙。
rs.freeze(100) //秒為單位,表示凍結(jié)多長時間
如果在主節(jié)點上執(zhí)行rs.freeze(0) 可以將退位的主節(jié)點重新變?yōu)橹鞴?jié)點羔巢。
使用維護模式
當在副本集的某個成員上執(zhí)行一個非常耗時的功能的話望忆,可以設置該成員進入維護模式,方式如下:
db.adminCommand({“replSetMaintenanceMode”:true});
要從維護模式中恢復的話竿秆,設置為false就可以了启摄。
不作為復制源
如果希望能從主節(jié)點復制數(shù)據(jù),可以把所有的備份成員的alloChaining設置為false幽钢。