- 求職 : Linux運(yùn)維
- 論壇徽章:
- 203
|
MongoDB復(fù)制集(3.0版本)之間通過(guò)心跳信息來(lái)同步成員的狀態(tài)信息,每個(gè)節(jié)點(diǎn)會(huì)周期性的向復(fù)制集內(nèi)其它的成員發(fā)送心跳信息來(lái)獲取狀態(tài),如rs.status()看到的復(fù)制集狀態(tài)信息。
一次心跳請(qǐng)求分3個(gè)階段 (主動(dòng)發(fā)起心跳請(qǐng)求的節(jié)點(diǎn)稱為源,接受到心跳請(qǐng)求的成為目標(biāo))
源向目標(biāo)發(fā)送心跳請(qǐng)求
目標(biāo)處理心跳請(qǐng)求,并向源發(fā)送應(yīng)答
源接受到心跳應(yīng)答,更新目標(biāo)節(jié)點(diǎn)狀態(tài)
接下來(lái)將介紹這3個(gè)階段里的主要狀態(tài)同步邏輯
階段1
默認(rèn)配置下,復(fù)制集的節(jié)點(diǎn)每隔2s會(huì)向其他成員發(fā)送一次心跳請(qǐng)求,即發(fā)送replSetHeartbeat命令請(qǐng)求,心跳請(qǐng)求的內(nèi)容類似如下(通過(guò)mongosniff抓包獲取),主要包含replSetName、發(fā)送心跳的節(jié)點(diǎn)地址、復(fù)制集版本等。
command: replSetHeartbeat database: admin metadata: { $replData: 1 } commandArgs: { replSetHeartbeat: "mongo-9552", pv: 1, v: 22, from: "10.101.72.137:9552", fromId: 3, checkEmpty: false }
階段2
復(fù)制集成員收到心跳請(qǐng)求后,就開(kāi)始處理請(qǐng)求,并將處理的結(jié)果回復(fù)給請(qǐng)求的節(jié)點(diǎn)。
如果自身不是復(fù)制集模式、或復(fù)制集名稱不匹配,則返回錯(cuò)誤應(yīng)答
如果源節(jié)點(diǎn)的復(fù)制集配置(rs.conf()的內(nèi)容)版本比自己低,則將自身的配置加入到心跳應(yīng)答消息里
將節(jié)點(diǎn)自身的oplog及其他狀態(tài)信息等加入到心跳應(yīng)答消息
如果自身是未初始化狀態(tài),則立即向源節(jié)點(diǎn)發(fā)送心跳請(qǐng)求,以更新復(fù)制集配置
commandReply: { ok: 1.0, time: 1460705698, electionTime: new Date(6273289095791771649), e: true, rs: true, state: 1, v: 22, hbmsg: "", set: "mongo-9552", opTime: new Date(6272251740930703361) } metadata: { $replData: { term: -1, lastOpCommitted: { ts: Timestamp 1460372410000|1, t: -1 }, lastOpVisible: { ts: Timestamp 0|0, t: -1 }, configVersion: 22, primaryIndex: 2, syncSourceIndex: -1 } }
階段3
階段3是最主要的處理部分,節(jié)點(diǎn)收到心跳應(yīng)答后,會(huì)根據(jù)應(yīng)答消息來(lái)更新對(duì)端節(jié)點(diǎn)的狀態(tài),并根據(jù)最終的狀態(tài)確定是否需要進(jìn)行重新選舉。
收到心跳應(yīng)答時(shí),如果是錯(cuò)誤應(yīng)答(心跳消息超時(shí)未應(yīng)答相當(dāng)于收到了錯(cuò)誤應(yīng)答),則
如果當(dāng)前重試次數(shù) <= kMaxHeartbeatRetries(默認(rèn)為2),并且上一次發(fā)送心跳在kDefaultHeartbeatTimeoutPeriod(默認(rèn)為10)時(shí)間內(nèi),則立即發(fā)送下一次心跳
當(dāng)失敗次數(shù)超過(guò)kMaxHeartbeatRetries,或者上一次心跳時(shí)間到現(xiàn)在超過(guò)kDefaultHeartbeatTimeoutPeriod,則認(rèn)為節(jié)點(diǎn)down
如果對(duì)端的復(fù)制集版本比自己高,則更新自己的配置并持久化到local數(shù)據(jù)庫(kù)中
根據(jù)應(yīng)答消息更新對(duì)端的狀態(tài)信息
如果自身是主節(jié)點(diǎn),當(dāng)發(fā)現(xiàn)有優(yōu)先級(jí)更高的節(jié)點(diǎn)可被選為主,則主動(dòng)降級(jí)
如果其他是主節(jié)點(diǎn),但自身有更高的優(yōu)先級(jí)并可被選為主,則會(huì)主動(dòng)要求主節(jié)點(diǎn)降級(jí)(目前這個(gè)邏輯實(shí)現(xiàn)有bug,主要靠主節(jié)點(diǎn)主動(dòng)降級(jí)來(lái)保證優(yōu)先級(jí)最高的節(jié)點(diǎn)最終會(huì)變成主, https://jira.mongodb.org/browse/SERVER-23630)
如果當(dāng)前沒(méi)有主節(jié)點(diǎn),則主動(dòng)發(fā)起新的選舉,當(dāng)?shù)玫酱蠖鄶?shù)節(jié)點(diǎn)同意后,即可選出新的主節(jié)點(diǎn)
總的來(lái)說(shuō),MongoDB通過(guò)心跳來(lái)同步節(jié)點(diǎn)間信息并觸發(fā)選舉,最終將復(fù)制集達(dá)到統(tǒng)一的狀態(tài),但過(guò)程的正確性沒(méi)有理論依據(jù),MongoDB-3.2版本里,使用了新版本的復(fù)制集通信協(xié)議,改用raft來(lái)選舉,能進(jìn)一步降低故障發(fā)現(xiàn)恢復(fù)時(shí)間 |
|