Why MIT6.824 course lab2(raft) doesn't suggest us use time.timer?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction to MIT 6.824 and Raft
The MIT 6.824 course is a class on distributed systems focusing on the principles and practices involved in the design and implementation of such systems. One of the key components of this class is Lab 2, which revolves around implementing Raft, a consensus algorithm that ensures distributed systems achieve agreement on shared state even in the presence of failures.
Raft and Its Challenges
Raft is used to manage a replicated log across distributed systems to achieve consistency through a series of elections and log replication procedures. It utilizes timers to trigger elections and to manage heartbeat messages, which are critical to ensure all nodes in the cluster maintain a consensus about the system's state.
Why Not time.Timer?
time.Timer in Go provides a way to perform a single action after a delay. While this can seem ideal for implementing Raft timeouts, there are specific reasons why its use is generally discouraged in the context of MIT 6.824's Raft implementation:
Immutability of Timers
Once a time.Timer is started, modifying the timer (e.g., stopping it or changing its period) is not straightforward and can lead to race conditions if not handled very carefully. Raft implementation frequently adjusts timers based on various triggers (like receiving a message), which makes mutable timers a necessity.
Precision and Overhead
time.Timer can introduce unnecessary overhead and complexity. Because time.Timer runs in its own goroutine, each timer adjustment involves communication between goroutines, potentially leading to higher resource utilization and reduced precision due to scheduling delays.
Scalability and Performance
In a distributed system like Raft, where timely responses are crucial for leader elections and log replication, any delay or overhead can degrade the system's overall performance and reliability. Managing multiple instances of time.Timer could also impact scalability as each node in the Raft cluster would need to handle its timers individually.
Alternative: Ticker Based Approach
A better approach often suggested is using a ticker-based system. Unlike time.Timer, time.Ticker provides periodic signals until stopped. This feature can be integrated efficiently into Raft's event loop, handling timeouts and periodic heartbeats in a scalable and manageable fashion.
Managing Timeouts with Ticker
Tickers can be adjusted more easily within the event loop by simply restarting the ticker with a new duration whenever necessary. This approach minimizes the risk of race conditions and enables quicker and more reliable timeout management.
Custom Timer Management
An alternative design could involve managing timers manually within the main event loop, providing even greater control over scheduling and handling. This method would keep all timeout logic centralized, reducing the complexity and overhead associated with handling multiple goroutines for timers.
Conclusion
While time.Timer might initially seem suitable for tasks requiring simple delays, its characteristics and the nature of operations necessary in a consensus algorithm like Raft make tickers a more appropriate and efficient choice. Utilizing tickers or a custom timer management system ensures that timer invocations align more predictably with the state machine's requirements, leading to a more robust and responsive Raft implementation.
Summary Table
| Feature | time.Timer | Ticker-based System |
| Mutability | Limited | High |
| Performance | Possible overhead | More efficient |
| Scalability | Medium | High |
| Complexity | High (race conditions) | Lower |
| Precision | Lower due to scheduling | Higher |
This comparative analysis shows why a ticker-based system or a custom timer management strategy might be preferred over using time.Timer in complex, time-sensitive applications like Raft in MIT 6.824.
Related reading
- Why not use heap sort always
- Why or why not use RequestVote RPC as heartbeat in Raft implementation?
- Why prefer start end - start / 2 over start end / 2 when calculating the middle of an array?
- Why Q.head Q.tail 1 represents the queue is full in CLRS
- Why Selection sort can be stable or unstable
- Why SortedSetT.GetViewBetween isn't Olog N?
- Why spark.ml don't implement any of spark.mllib algorithms?
- Why the tree resulting from Kruskal is different from Dijkstra?

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.