Logical Time and Causal Ordering

In distributed systems, physical time is unreliable due to clock drift and network latency. To reason about the sequence of events, we use logical time, which focuses on causality—the "happened-before" relation—rather than wall-clock time.

1. The "Happened-Before" Relation (\to)

The relation\todefines a strict partial order on events in a system. Formally, for two eventsaandb:

  1. Process Order: Ifaandboccur in the same process andaoccurs beforeb, thena \to b.
  2. Communication Order: Ifais the sending of a message andbis the receipt of that message, thena \to b.
  3. Transitivity: Ifa \to bandb \to c, thena \to c.

Ifa \not\to bandb \not\to a, thenaandbare concurrent (a \parallel b).

2. Lamport Clocks (Scalar Clocks)

A Lamport clock is a simple monotonically increasing counter maintained by each process.

2.1 The Update Algorithm

Each processP_imaintains a local counterL_i.

  1. Before an event (internal, send, or receive),P_iincrements its clock:
L_i = L_i + 1
  1. When sending a message,P_iincludes its currentL_iin the message payload.
  2. When receiving a message with timestampL_{msg},P_iupdates its clock:
L_i = \max(L_i, L_{msg}) + 1

2.2 Mathematical PropertyThe Lamport clock satisfies the Clock Consistency Condition:

a \to b \implies L(a) < L(b)

Note: The converse is NOT true. IfL(a) < L(b), we cannot concludea \to b. They could be concurrent.

3. Vector Clocks

To detect concurrency (i.e., to make the clock condition a bidirectional implication), we use Vector Clocks.

3.1 The Vector Update Algorithm

In a system withNprocesses, each processP_imaintains a vectorV_iof sizeN, whereV_i[j]isP_i's knowledge of the clock of processP_j.

  1. Before an internal event,P_iincrements its own component:
V_i[i] = V_i[i] + 1
  1. When sending a message,P_iincludes its entire vectorV_iin the message.
  2. When receiving a message with vectorV_{msg},P_iupdates every element of its vector:
V_i[j] = \max(V_i[j], V_{msg}[j]) \quad \text{for all } j

And then increments its own component:

V_i[i] = V_i[i] + 1

3.2 Comparison and Concurrency DetectionFor two vector timestampsuandv:

Concurrency Detection: Eventsaandbare concurrent (a \parallel b) if and only ifV(a) \not\le V(b)andV(b) \not\le V(a). In other words, the vectors are incomparable.

4. Practical Implications

4.1 Conflict Resolution in Databases

Dynamo-style databases (e.g., Riak, Cassandra) use vector clocks (or the optimized "Dotted Version Vectors") to detect concurrent writes to the same key. If two versions of an object have incomparable vector clocks, the system knows a conflict has occurred and can trigger "Sibling" resolution or manual reconciliation.

4.2 Causal Consistency

By attaching vector clocks to data, a system can ensure that a user never sees an "effect" before its "cause." For example, if a comment is a reply to a post, the reply will only be shown if the post is already visible in the local view.

5. Summary