Lab 2C: Raft – Persistence

Deadline: 4/29 23:59:59 EST

Introduction

If a Raft-based server reboots it should resume service where it left off. This requires that Raft keep persistent state that survives a reboot. The paper's Figure 2 mentions which state should be persistent.

A real implementation would write Raft's persistent state to disk each time it changed, and would read the state from disk when restarting after a reboot. Your implementation won't use the disk; instead, it will save and restore persistent state from a Persister object (see persister.go). Whoever calls Raft.Make() supplies a Persister that initially holds Raft's most recently persisted state (if any). Raft should initialize its state from that Persister, and should use it to save its persistent state each time the state changes. Use the Persister's ReadRaftState() and Save() methods.

To start, remember checking out to the new branch first:

$ git checkout -b lab2c

Complete the functions persist() and readPersist() in raft.go by adding code to save and restore persistent state. You will need to encode (or "serialize") the state as an array of bytes in order to pass it to the Persister. Use the labgob encoder; see the comments in persist() and readPersist(). labgob is like Go's gob encoder but prints error messages if you try to encode structures with lower-case field names. For now, pass nil as the second argument to persister.Save(). Insert calls to persist() at the points where your implementation changes persistent state. Once you've done this, and if the rest of your implementation is correct, you should pass all of the 2C tests.

You will probably need the optimization that backs up nextIndex by more than one entry at a time. Look at the extended Raft paper starting at the bottom of page 7 and top of page 8 (marked by a gray line). The paper is vague about the details; you will need to fill in the gaps. One possibility is to have a rejection message include:

    XTerm:  term in the conflicting entry (if any)
    XIndex: index of first entry with that term (if any)
    XLen:   log length

Then the leader’s logic can be something like:

  Case 1: leader doesn't have XTerm:
    nextIndex = XIndex
  Case 2: leader has XTerm:
    nextIndex = leader's last entry for XTerm
  Case 3: follower's log is too short:
    nextIndex = XLen

A few other hints:

  • The 2C tests are more demanding than those for 2A or 2B, and failures may be caused by problems in your code for 2A or 2B.

Your code should pass all the 2C tests (as shown below), as well as the 2A and 2B tests.

$ go test -run 2C
Test (2C): basic persistence ...
  ... Passed --   5.0  3   86   22849    6
Test (2C): more persistence ...
  ... Passed --  17.6  5  952  218854   16
Test (2C): partitioned leader and one follower crash, leader restarts ...
  ... Passed --   2.0  3   34    8937    4
Test (2C): Figure 8 ...
  ... Passed --  31.2  5  580  130675   32
Test (2C): unreliable agreement ...
  ... Passed --   1.7  5 1044  366392  246
Test (2C): Figure 8 (unreliable) ...
  ... Passed --  33.6  5 10700 33695245  308
Test (2C): churn ...
  ... Passed --  16.1  5 8864 44771259 1544
Test (2C): unreliable churn ...
  ... Passed --  16.5  5 4220 6414632  906
PASS
ok  	6.5840/raft	123.564s
$

It is a good idea to run the tests multiple times before submitting and check that each run prints PASS.

$ for i in {0..10}; do go test; done

Submission

Required: DESIGN DOC Please fill in a new file DESIGN_DOC and add to your repo root directory (together with student_info). This document is for you to share your experience and will be graded as part of your submission. You can refer to this template. Do not forget to add it in git!

To submit, push your commits in local lab2c branch to Github.

$ git push -u origin lab2c

Our grading scripts will automatically take a snapshot of your lab branch at the submission deadline (unless you use the late tokens, in this case your codes will be graded later). Make sure you check in all commits to the correct branch and do not submit new commits that may break the compilation. If you decide to use the late hour tokens, by the deadline send an email to cs4740staff@virginia.edu with the subject “[Late Request]: $GitHub_Repo_Name$” (empty content is fine) so we won’t be collecting and grading your solution immediately. When you finish (within the token limit), send another email to cs4740staff@virginia.edu with the subject “[Late Finish]: $GitHub_Repo_Name$”.