作者: Unmesh Joshi
譯者: java達(dá)人
預(yù)寫日志中的索引,顯示最近一次成功的復(fù)制。
問題
服務(wù)器崩潰并重新啟動(dòng)后,可使用“Write-Ahead Log”模式恢復(fù)狀態(tài)。但是,如果服務(wù)器發(fā)生故障,Write-Ahead Log不足以提供可用性。如果單個(gè)服務(wù)器發(fā)生故障,則客戶端將無法運(yùn)行,直到服務(wù)器重新啟動(dòng)。為了獲得更多可用的系統(tǒng),我們可以在多個(gè)服務(wù)器上復(fù)制日志。使用領(lǐng)導(dǎo)者和追隨者模式,領(lǐng)導(dǎo)者會(huì)將其所有日志條目復(fù)制到追隨者法定數(shù)。現(xiàn)在,如果領(lǐng)導(dǎo)者失敗,則可以選舉新的領(lǐng)導(dǎo)者,并且客戶可以像以前一樣繼續(xù)使用集群。但是仍然有幾處可能出問題:
? leader在將其日志發(fā)送給任何追隨者之前可能會(huì)失敗。? 領(lǐng)導(dǎo)者可能會(huì)在向一些追隨者發(fā)送日志條目時(shí)失敗,無法將其發(fā)送給大多數(shù)的追隨者。
在這些錯(cuò)誤場(chǎng)景中,一些追隨者可能在其日志中丟失條目,而一些追隨者可能擁有比其他追隨者更多的條目。因此,對(duì)于每個(gè)follower來說,了解日志的哪一部分對(duì)客戶端是安全可用的就變得很重要了。
解決方案
high-water mark是日志文件的一個(gè)索引,它記錄已知已成功復(fù)制到追隨者Quorum的最后一個(gè)日志條目。在復(fù)制過程中,領(lǐng)導(dǎo)者還會(huì)將high-water mark傳遞給追隨者。集群中的所有服務(wù)器應(yīng)該只向請(qǐng)求低于high-water mark更新的客戶端傳輸數(shù)據(jù)。
這是操作順序:
Figure 1: High-Water Mark
對(duì)于每個(gè)日志條目,leader將其附加到其本地預(yù)寫日志中,然后將其發(fā)送給所有追隨者。
leader (class ReplicationModule...)
private Long appendAndReplicate(byte[] data) { Long lastLogEntryIndex = appendToLocalLog(data); logger.info("Replicating log entries from index " + lastLogEntryIndex); replicateOnFollowers(lastLogEntryIndex); return lastLogEntryIndex; }
private void replicateOnFollowers(Long entryAtIndex) { for (final FollowerHandler follower : followers) { replicateOn(follower, entryAtIndex); //send replication requests to followers } }
追隨者處理復(fù)制請(qǐng)求并將日志條目附加到它們的本地日志中。在成功附加日志條目之后,它們將擁有的最新日志條目索引響應(yīng)到leader。該響應(yīng)還包括服務(wù)器的當(dāng)前Generation Clock。
follower (class ReplicationModule...)
private ReplicationResponse handleReplicationRequest(ReplicationRequest replicationRequest) { List
Leader在收到響應(yīng)時(shí)跟蹤在每個(gè)服務(wù)器上復(fù)制的日志索引。
class ReplicationModule…
recordReplicationConfirmedFor(response.getServerId(), response.getReplicatedLogIndex()); long logIndexAtQuorum = computeHighwaterMark(logIndexesAtAllServers(), config.numberOfServers()); if (logIndexAtQuorum > replicationState.getHighWaterMark()) { var previousHighWaterMark = replicationState.getHighWaterMark(); applyLogAt(previousHighWaterMark, logIndexAtQuorum); replicationState.setHighWaterMark(logIndexAtQuorum); }
通過查看所有追隨者的日志索引和領(lǐng)導(dǎo)者本身的日志,并獲取大多數(shù)服務(wù)器上可用的索引,可以計(jì)算出High-Water Mark。
class ReplicationModule…
Long computeHighwaterMark(List
領(lǐng)導(dǎo)者將high-water mark作為常規(guī)心跳的一部分或作為單獨(dú)的請(qǐng)求向追隨者傳播。追隨者隨后相應(yīng)地設(shè)定了他們的high-water mark。
-
服務(wù)器
+關(guān)注
關(guān)注
12文章
9029瀏覽量
85207 -
分布式系統(tǒng)
+關(guān)注
關(guān)注
0文章
146瀏覽量
19204 -
Mark
+關(guān)注
關(guān)注
0文章
17瀏覽量
8386
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論