Raft Project 2 Review/Discussion (Winter 2023)

Click here for .cc file containing examples.

Everyone made improvements from Project 1.

  • Deeper classes (simpler APIs, less specialization & information leakage)
    • Network communication pretty good in every project
  • Better error detection and logging (but still more work to do)

Class Design: Together vs. Apart

Given various pieces of functionality, which belong together in the same class/method and which should be separated in different classes/methods?

Key considerations:

  • Separate general-purpose and special-purpose code
    • Over-specialization creates information leakage
  • Combine things that are related, separate things that are not related
    • Do one thing at a time
  • Do the whole job in one place

Examples:

  • Raft server contains state machine for shell?
  • Client main program also has code to communicate with Raft cluster?
  • One communication library for both server-server and client-server communication
  • Raft server also manages communication with clients?
  • Log class also manages other persistent state such as term and vote?
  • Separate code for sending heartbeats and AppendEntries requests (no log entries in heartbeats)?
  • Single method handles transitions to all states?

Correctness Issues

Restarting server when state files don't exist: just reinitialize?

Reinitializing server when state files exist: reuse?

Respond to AppendEntries request with new log length?

When processing successful AppendEntries responses, use local log size to update matchIndex and nextIndex?

When it becomes clear that election is lost, start new election immediately?

When invoking state machine, call waitpid before reading output?

Check for existence of state files on startup; after that, assume they exist?

Performance Issues

Log overheads that scale with size of the log:

  • Scan entire log at startup or during operations
  • Keep index for entire log in memory
  • Rewrite entire index for each modification
  • These shouldn't be necessary: only the most recent entries are likely to be accessed.

Lots of copying of messages

Smaller Stuff

Readable code examples: why is one easier to read than the other?

Creating useful exception super-classes