raft理論與實踐[5]-lab2c-持久化

準備工作

1、閱讀raft論文
2、閱讀raft理論與實踐[1]-理論篇
3、閱讀raft理論與實踐[2]-lab2a
4、閱讀raft理論與實踐[3]-lab2a講解
5、閱讀raft理論與實踐[4]-lab2b日誌複製
6、查看我寫的這篇文章: 模擬RPC遠程過程調用

持久化

  • 如果基於Raft的服務器重新啓動,則應從中斷的位置恢復服務。 這就要求Raft保持持久狀態,使其在重啓後仍然有效。

  • 論文中Figure 2指出了那些字段需要持久化。

  • 並且raft.go包含有關如何保存和恢復持久性狀態的示例。

  • 一個“真實的服務在每次Raft更改狀態時將Raft的持久狀態寫入磁盤,並在重新啓動時從磁盤讀取最新的狀態來恢復。

  • 但是我們的實現將會採用一個結構體的方式來模擬實現persister.go。

  • 調用Raft.Make()會提供一個Persister,它持有Raft的最近持久狀態。

  • Raft應從該Persister初始化其狀態,並在每次狀態更改時修改其持久狀態。

  • 主要使用Persister的ReadRaftState()和SaveRaftState()方法。

  • 在本實驗中,我們需要完善在raft.go中的persist() and readPersist()方法。

  • 需要使用到labgob包中的編碼與解碼函數。

  • 你需要明確在什麼時候需要持久化。

下面只列出兩個重要實現,其他不再贅述,留給讀者自己實現。

持久化編碼

func (rf *Raft) persist() {
    // Your code here (2C).
    w := new(bytes.Buffer)

    e:= labgob.NewEncoder(w)
    e.Encode(rf.CurrentTerm)
    e.Encode(rf.VotedFor)
    e.Encode(rf.Logs)

    data := w.Bytes()
    rf.persister.SaveRaftState(data)
}

持久化解碼

func (rf *Raft) readPersist(data []byte) {
    if data == nil || len(data) < 1 { // bootstrap without any state?
        return
    }
    // Your code here (2C).
    r := bytes.NewBuffer(data)

    d:= labgob.NewDecoder(r)
    d.Decode(&rf.CurrentTerm)
    d.Decode(&rf.VotedFor)
    d.Decode(&rf.Logs)
}

測試

> go test -v -run=2C

參考資料

github.com/dreamerjacks


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章