Vector Clocks: Tracking Causality in Distributed Systems
A vector clock is an array of counters, one for each node, that tracks causality across a distributed system. It's how databases resolve conflicting writes.
WHY IT EXISTS: In a distributed system, there is no single, reliable source of truth for time. Simple timestamps can't distinguish between an event that happened later and an event that happened concurrently on a different machine. Vector clocks were created to solve this by explicitly tracking causality, not just time.
THE MENTAL MODEL: Think of a vector clock as a list of counters, [N1, N2, N3, ...], where each position represents a node in the system. Every node maintains its own version of this list. The number at its own position is its personal logical clock. The numbers at other positions represent the latest clock value that this node has heard about from those other nodes. It’s a node's local, best-effort view of the entire system's state history.
HOW IT WORKS: A system with N processes uses a vector of N integers. Each process starts with a vector of all zeros, like [0, 0, 0]. When a process has an internal event, it increments its own counter in the vector. When it sends a message, it first increments its counter, then attaches its entire vector clock. The receiving process updates its clock by taking the element-wise maximum of its own clock and the received clock. This update merges the sender's history into the receiver's history.
WHEN TO USE IT: Use vector clocks when you need to know if one event could have possibly influenced another. This is essential for optimistic replication in key-value stores (like Riak or DynamoDB) to detect write conflicts. If two versions of a key arrive, the system can compare their vector clocks to see if one happened before the other or if they are in conflict and need reconciliation.
WHEN NOT TO USE IT: Avoid vector clocks in systems with a very large or highly dynamic number of nodes. The size of the vector grows linearly with the number of nodes, which can become a significant overhead in messages and storage. If you only need a simple, arbitrary ordering and not strict causality detection, Lamport timestamps are a more lightweight alternative.
ONE CANONICAL EXAMPLE: Imagine a two-node system, A and B, with clocks starting at [0, 0]. Node A performs a write, its clock becomes [1, 0]. It sends this data to B. B receives it, merges the clock by taking max([0,0], [1,0]) to get [1,0], then performs its own write, making its clock [1, 1]. Now, B's clock [1, 1] shows that its state is aware of A's state up to event 1. If A and B had written concurrently without communication, their clocks might be [1, 0] and [0, 1]. Neither clock is strictly greater than the other, which signals a causality violation or concurrent event.
Read the original → en.wikipedia.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.