Part II — Failure, replication, agreement · Chapter 5

Replication, consistency and CAP

~27 min3 instrumentsA.Y. 2025/26 · Prof. Omicini
M3 Replication & Consistency in Distributed SystemsC1 The CAP Theorem
The question

Once data lives in several copies, what may a reader see, and what must we give up when the network splits?

The argument in one paragraph

Replication buys reliability, performance and scale, but copies drift, and keeping them identical needs the global synchronisation replication was meant to avoid. The way out is to relax consistency and write the relaxation down as a contract. Data-centric models state what all processes may observe (bounded deviation, sequential, causal); eventual consistency only promises convergence; client-centric models promise a single mobile client that its own view never goes backwards. The hard limit is the CAP theorem: during a network partition, a replicated service cannot answer every request and stay atomically consistent; without a partition it can do both. Most large services choose availability and live with BASE.

Why replicate, and what it costs

M3 borrows heavily from Tanenbaum & van Steen [2017]. Replication keeps several copies of the same data on different machines, for three reasons:

  1. Reliability. If a replica of a file system crashes, operation continues on another. With three copies, and every read and write done on each, a single failing write is hidden by trusting the value at least two copies return.
  2. Performance. Many processes hitting one server: replicate the server and divide the workload.
  3. Scaling, in numbers and in geographical area. A copy near the process that uses it cuts access time, so performance as perceived by that process increases.

But keeping replicas up to date consumes bandwidth: is there a benefit overall? At first glance the benefits look unquestionable:

  1. reliability
  2. fault tolerance
  3. accessibility
  4. performance
  5. scalability

So should we just replicate data, processes, whatever, and be content with it? No: replication has its own problems.

  1. Costs. Replicas need (new?) machines elsewhere, possibly bought and placed near the processes using the data: more management costs (physical spaces, technical personnel, …), possibly acquisition costs.
  2. Computational resources. Copies must be kept consistent, which takes computation within replicas…
  3. Bandwidth. …and communication among them.
  4. Consistency, the main problem. A modified copy differs from the others, so the modification must be carried out on all copies. When and how modifications are carried out determines the cost of replication.

Two examples of the cost

Web caching. Browsers cache fetched pages, so a page requested again appears instantly. But if the page changed on the server, the user gets a stale copy. Preventing that hurts either way:

  1. Forbid caching: perceived performance suffers badly.
  2. The server invalidates or updates cached copies: it must track every cache and message it, a heavy load with poor scalability.

Access versus update rate. A process P reads a local replica N times per second; the replica is updated M times per second, each update fully refreshing it. If N ≪ M, most versions shipped are never read, and their network traffic is wasted. Is the local replica worth it, or should updates propagate differently?

The replication and consistency dilemma

Scalability problems usually show up as performance problems, and replication and caching are the standard cure. But keeping copies consistent can itself become a scalability problem. Intuitively, copies are consistent when they are always the same, so a read at any copy returns the same result. Then an update must reach all copies before any subsequent operation: synchronous replication, whose result is informally called tight consistency.

The key idea is to update all copies as one atomic operation, or transaction. That is hard when operations must also be fast: replicas must first agree on when exactly each update is applied, e.g. on a global order of operations (Ch. 2's bank replicas). Global synchronisation takes a lot of communication, and the slides ask whether we are “bumping into another set of impossibility theorems”. We are: CAP (§6) and FLP (Ch. 6).

Is the cure worse than the disease? There is no general answer, but often a solution: relax the consistency constraints. Drop atomic updates, avoid instantaneous global synchronisation, gain performance, and accept that replicas are not always the same. When and how far that is acceptable depends on the access and update patterns of the data and on the purpose of its use.

Consistency as a contract

Instead of one notion of consistency we can define several, each fitting different scenarios, so that engineers can trade the costs of consistency against its benefits. Each consistency model can then be implemented by different protocols, whose features affect how well it works.

Historically, the first things to be distributed are data. So the first problem is consistency of data across copies, and the actions to account for are operations over data. The setting is a data store: logically one store, physically distributed and replicated across processes, each working on a local or nearby copy.

Process P1Process P2Process P3 local copy local copy local copy distributed data store · updates propagate between copies
Fig. 5.1 — General organisation of a distributed data store [Tanenbaum & van Steen, 2017]. Each process reads and writes its nearby copy; the store is one object only logically.
Consistency model[M3, after Tanenbaum & van Steen, 2017]

A consistency model is essentially a contract among the processes and the data store, ensuring the correctness of data given a set of rules that processes have to follow.

What is “correct” depends on what processes expect, which is hard to define without a global notion of time (Ch. 2). The definition shifts the focus from the replicated data to the processes using it and their application needs. Different needs, different contracts, in two families: data-centric models constrain what all processes observe; client-centric models what one client observes.

Data-centric models

Continuous consistency: bounding the deviation

The first contract does not demand equal copies; it imposes limits on the deviation between replicas. The level of consistency is set along three independent axes:

  1. Numerical deviation, absolute or relative: two copies of a stock price should not differ by more than $0.01.
  2. Staleness deviation: weather data should not be more than four hours stale.
  3. Ordering deviation: in a bulletin board, at most six messages may be out of order.

These bounds define continuous consistency. Deviation is measured on a unit of consistency, the conit. A data store's nature suggests its conit, but the model (and replication) is defined around a suitably designed one, and deviation is measured as differences of conits. There is no absolute measure: choose the conit for the resource and problem at hand. Granularity matters (Fig. 5.2).

(a) one conit {x, y} (b) two conits {x}, {y} ABAB x ← 5 y ← 2 x y x ← 5 y ← 2 x y 2 unpropagated → must propagate 1 unpropagated each → no traffic rule: at most 1 unpropagated update per conit at a replica
Fig. 5.2 — Choosing the granularity of a conit [Tanenbaum & van Steen, 2017]. The same two updates at A force propagation with a larger conit (a), and none with smaller ones (b).

Ordering operations

The next models come from parallel and concurrent environments, where processes access shared resources simultaneously. To commit to a state for the replicas, processes must agree on a global ordering of updates.

Sequential consistency[M3, after Tanenbaum & van Steen, 2017]

Main idea: all update operations are seen by all processes in the same order. A data store is sequentially consistent when the result of any execution is the same as if

  1. the (read and write) operations by all processes on the data store were executed in some sequential order, and
  2. the operations of each individual process appear in this sequence in the order specified by its program.

Any interleaving will do, if one exists and everybody sees it; real time plays no role. Take two processes, with x = y = 0 initially:

P1: W(x)1; R(y)?   ·   P2: W(y)1; R(x)?

Can both reads return 0? R(y) must then precede W(y)1, and R(x) precede W(x)1. With program order that is a cycle: W(x)1 → R(y) → W(y)1 → R(x) → W(x)1. No sequential order exists, so sequential consistency forbids both reads returning 0; every other combination is allowed. This “store buffer” history is Instrument 1's first preset.

Causal consistency[M3, after Tanenbaum & van Steen, 2017]

A data store is causally consistent when all processes see write operations that are in a cause/effect relation in the same order.

It weakens sequential consistency: ordering is limited to operations in a cause/effect relation, and concurrent writes may be seen in different orders by different processes. The relation is happens-before (Ch. 2) on operations: program order, plus a read follows the write whose value it returns (write as send, read as receive). Every sequentially consistent history is causally consistent, since its single order respects causality. Not conversely: the store-buffer history is causally consistent, because its two writes are concurrent.

Eventual consistency

The slides introduce the weakest model at the start of the client-centric part, as the scenario that motivates it: a large distributed data store with almost no update conflicts. Typically a single authority updates and many processes read, so the only conflict is read-write: one process updates an item while another reads it (DNS changes, Web content). Readers may get non-updated data, which is mostly acceptable. If no update takes place for a while, all replicas gradually become consistent: eventual consistency. It promises convergence, so it allows any finite history whose reads return already-written values, provided replicas agree once updates stop.

Instrument 1History checker

Pick a history (all variables start at 0) or type your own, one line per process, e.g. W(x)1 R(y)0. The checker searches for a sequential order, for causally consistent per-process views, and for values nobody wrote.

Client-centric models

Switch perspective to data sharing in mobile computing. A client connects to different replicas over time, and their differences should be transparent (Ch. 1). Simultaneous updates are not the issue. An eventually consistent store works while a client always talks to the same replica; when it moves, the new replica may lack what the client saw, or wrote, a minute ago.

Client-centric consistency[M3]

Client-centric consistency models ensure that whenever a client connects to a new replica, that replica is up to date according to the client's previous accesses to the same data at other replicas. Consistency no longer refers to the resource itself (its nature, its dynamics) but to the view each client has of it.

Four client-centric models [M3]

  1. Monotonic reads. If a process reads the value of a data item x, any successive read operation on x by the process will always return that same value or a more recent value. Example: a distributed e-mail database; mail you have seen does not vanish when you reconnect elsewhere.
  2. Monotonic writes. A write operation by a process on a data item x is completed before any successive operation on x by the same process. Idea: the order of updates is maintained over distributed replicas. Example: a software library under development, where each new version builds on the previous one.
  3. Read your writes. The effect of a write operation by a process on data item x will always be seen by a successive read operation on x by the same process. Idea: avoid the “web page failed update” effect. Example: updating a password.
  4. Writes follow reads. A write operation by a process on data item x following a previous read operation on x by the same process is guaranteed to take place on the same or a more recent value of x that was read. Idea: writes affect only up-to-date data items. Example: comments to posts on Facebook.
Slide note · monotonic writes

The slide says “any successive operation”; Tanenbaum & van Steen [2017] say any successive write, matching the slide's idea and example. A later read of your own write is read-your-writes.

The guarantees are per client and independent. Each covers one pair of operations by the same client at two replicas (Instrument 2).

Instrument 2Mobile client trace

A client does one operation at replica L1, moves, and does a second one at L2. Choose the two operations and whether L1's updates have reached L2 in between.

At L1
then at L2
Before the second operation, L2

What gets replicated, and with what

Supporting replication means deciding where, when and by whom replicas are placed, and which mechanisms keep them consistent. Replica management has two subproblems, and they are not the same problem:

  1. Placing replica servers: where the machines that host replicas go.
  2. Placing content: which data goes on which of those servers.

Replication is not merely of data. Service replication replicates functions, for the same reasons, which may or may not rely on the same data store: two layers, each with its own consistency and replication model. Process replication replicates processes in a mobile setting, which may require cloning or higher-level mechanisms such as goal-passing (Ch. 3).

The technology landscape

M3 ends with a “fast scan of the Web” of replication and consistency for fault tolerance:

Consistency typeKey mechanism / protocolTypical systems / tech
strongRaft, Paxosetcd, Spanner, CockroachDB
eventualGossip, Merkle treesDynamoDB, Cassandra, Riak
causalVector clocks, CRDTsAntidoteDB, Orleans, Akka
tunableQuorums (R/W)Cassandra, Dynamo-style DBs
transactionalConsensus + TrueTimeSpanner, CockroachDB
log-basedISR, CDC streamsKafka, Debezium, Aurora

The framing is the point: there is a lot to see before we can understand (almost) all of it, e.g. logical time (Ch. 2) and group and coordination algorithms (Ch. 6). The Kubernetes class (Ch. 9) gives concrete examples.

Beyond the slides · quorums (R/W)

With N replicas, a write waits for W acknowledgements and a read collects R answers. If R + W > N, every read quorum intersects every write quorum, so a read reaches at least one replica holding the latest completed write (recognised by its version). Tuning R and W trades latency against how many unreachable replicas each operation tolerates.

Replication. Theory and Practice [Charron-Bost et al., 2010] shows how much this basic course leaves out; after it, you should read that book proficiently. Other books: Kemme et al. [2010], Helal et al. [2002], Özsu & Valduriez [2020]; for MySQL, Bradford & Schneider [2012] and Schwartz et al. [2012]; for PostgreSQL, Böszörmenyi & Schönig [2013]; for Veeam, Childerhose [2022].

Lessons learnt · M3

  1. Replication is useful in distributed systems.
  2. Replication requires consistency.
  3. Consistency is not an absolute notion: different application needs mandate different models.
  4. We talk about data, yet nowadays we replicate whatever resource we need, e.g. cloning in mobile distributed systems.

The CAP theorem

Continuing to provide services in spite of failures is supposed to be a main benefit of distributed over centralised systems [Friedman & Birman, 1996]. The intuition: if a component fails, or is disconnected or partitioned, others replace it and hide the failure, or at least reduce its perceived impact. A system hiding (most of) its failures is highly available (Ch. 4). The design question: how much failure can a system sustain before failure is noticed?

We want systems consistent (correct replies) and available (live, making good things happen), yet they suffer power losses, crashes, network failures, message loss, malicious attacks, Byzantine failures: they are unreliable [Gilbert & Lynch, 2012]. Hence: “The CAP theorem is one example of a more general tradeoff between safety and liveness in unreliable systems.”

The statement

Informally, it is only possible to provide any two of consistency (C), availability (A) and partition tolerance (P) [Shim, 2012]. In Zhao's [2014] words: C, replicated data is always consistent; A, data is highly available to users; P, the system keeps providing services when the network partitions. The first formulation is Brewer's:

CAP (Brewer's conjecture)[Brewer, 2000]

A distributed database potentially features three desirable properties: Consistency, Availability, and tolerance towards network Partition. According to the CAP theorem, any shared-data distributed system can have at most two of these three.

An impossibility result: “we repent and renounce”. What is our sin? Distributed systems, that's what it is. So pick one to give up:

  1. CA: forget partition tolerance, and have consistency and availability.
  2. AP: forget consistency, and live with a partition-tolerant, highly available system.
  3. CP: forget availability, and enjoy a system that is both consistent and partition-tolerant.

But the three properties are not of the same sort, technically or conceptually:

  1. Consistency and availability range over a spectrum of options; partition tolerance is more of an on/off feature.
  2. All three are desirable, yet forfeiting partition tolerance is not really an option in real-world systems…
  3. …particularly with pervasive systems in the IoT era, where instability of the network rules [Grimm et al., 2004].
  4. Long story short, CAP most often forces us to choose between availability and consistency.
CAP weakerstrongerrarer answersalways answers during a partition: trade one for the other on/off · in practice always on
Fig. 5.3 — The spectrum view of slide 15: C and A are dials, P is a switch the network sets for you.

Example: location-based games

Location-based services use a user's or device's position to provide information, entertainment, security [Shekhar et al., 2016]; location-based games use it to evolve the gameplay (BotFighters, GeoZombie [Prandi et al., 2016], Ingress, Pokémon Go, Harry Potter: Wizards Unite, Minecraft Earth). Their CAP profile:

  1. P is not negotiable. Millions of players roam physical space with mobile devices, inherently unstable in connectivity. Players move in and out of coverage and concentrate in places, e.g. at special events. Scalability is multi-level: players overall, places, players per place. See the costly Chicago 2017 Pokémon Go Fest disaster.
  2. C matters. Consistent game data (goals, situation, achievements) keeps players in the game. Architectures are logically centralised, with spatial replication to cut perceived latency and improve scalability.
  3. A pays. When strong consistency is required, e.g. for in-game transactions, players wait while servers reach a consistent state. The first, usual casualty is availability: the Spinning Wheel of Death.

A detour: catching a Pokémon on Google Cloud

  1. Opening the app downloads all static media, stored in Cloud Storage; Cloud CDN (Google's global edge network, with Cloud Load Balancing) caches and serves them close to users.
  2. Requests go through an NGINX reverse proxy to the Frontend game service on Google Kubernetes Engine (GKE).
  3. The Spatial Query Backend keeps a cache sharded by location and decides which Pokémon, gyms and PokéStops are around, the time zone, …
  4. Catching a Pokémon sends an event to Google Spanner; the device gets its response when the write completes. Spanner is strongly consistent.
  5. Every action is recorded in Bigtable (as Protobuf) for logging and tracking, and sent to Pub/Sub for the analysis pipeline.
  6. Players in the same region stay in sync by determinism of the maps: at the same physical location, all players' inputs are the same, even on different machines.
  7. All servers stay in sync on settings and event timings, so players feel part of a shared world.

Note the mix: cached replicas for performance (1, 3), strong consistency only where a wrong answer is unacceptable (4), agreement by determinism instead of synchronisation (6).

Proving CAP

A proof needs a precise formulation. Gilbert & Lynch [2002] soon gave one, with some limitations; others followed. First, the concepts.

Availability[Gilbert & Lynch, 2002]

“For a distributed system to be continuously available, every request received by a non-failing node in the system must result in a response.” If the system is available, we get responses.

Consistency (atomic)[Gilbert & Lynch, 2002]

A consistent service is modelled as an atomic data object: operations are totally ordered, and each operation occurs in a single instant of time. Among the consequences, all read operations occurring after a write operation completes must return the value of that write or of a later one. If the system is consistent, we get correct responses.

This C is unlike ACID's: it encompasses both the A (atomicity) and the C (consistency) of ACID.

Network partition[Gilbert & Lynch, 2002]

“When a network is partitioned, all messages sent from nodes in one component of the partition to nodes in another component are lost.” “And, any pattern of message loss can be modelled as a temporary partition separating the communicating nodes at the exact instant the message is lost.”

Roughly: A sends a message to B. The network is partitioned if it does not reach B; availability is B responding; consistency is B's response being correct.

Beyond the slides · atomic = linearisable

Atomic consistency is today called linearisability [Herlihy & Wing, 1990]: sequential consistency (§3) whose single order also respects the real-time order of non-overlapping operations. So linearisable ⇒ sequential ⇒ causal. A read returning an old value after a write has completed is allowed by sequential consistency and forbidden by atomic consistency; CAP is about the latter.

The proof is given for three sorts of network:

  1. Asynchronous network with message loss.
  2. Asynchronous network without message loss.
  3. Partially synchronous network with local clocks.

The slides focus on the asynchronous model: no single clock; nodes act on local computation and received messages.

Theorem[Gilbert & Lynch, 2002]

“It is impossible in the asynchronous network model to implement a read/write data object that guarantees the following properties: availability; atomic consistency — in all fair executions (including those in which messages are lost).”

The proof, by indistinguishability

Assume, for contradiction, that atomicity, availability and partition tolerance all hold. Split the nodes into disjoint, non-empty sets G1, G2, with all messages between them lost. The atomic object o starts at v0.

Run α1 then α2. Nothing from G1 reached G2, so G2 cannot tell this run from α2 alone, where the answer must be v0. It returns v0 although v1's write has completed: atomic consistency is violated. Q.E.D. Instrument 3 replays it and shows the two ways out: answer and be stale (AP), or refuse and stay correct (CP).

Instrument 3Partition simulator

Two replicas of one object, initially v0. Choose a policy, cut the link, then write at G1 and read at G2. Replay the proof runs α1 then α2 for you.

    Beyond the slides · the other two network models

    Without message loss the asynchronous result still holds: a node cannot tell an arbitrarily delayed message from a lost one. With partial synchrony, local clocks allow timeouts, yet the impossibility remains once messages can be lost; only a weaker, time-bounded consistency becomes achievable [Gilbert & Lynch, 2002].

    Living with CAP: BASE

    Should we stop distributing systems, as we stopped using axiomatic systems after Gödel [1931]? Of course we did not. Negative results set the boundaries, and an impossibility result becomes a lever for effective engineering. Brewer later gave a very simple scheme [Brewer, 2012]:

    1. When the network is partitioned, a distributed system should choose a trade-off between consistency and availability.
    2. When there is no partition, a system can feature both consistency and availability.

    So CAP does not say you always lose a property; it says what to decide while the network is split (in Instrument 3, with the link up both policies answer correctly).

    ACID vs BASE

    ACID semantics (Atomicity, Consistency, Isolation, Durability) might be too strong [Fox et al., 1997]: “The design space for network services can be partitioned according to the data semantics that each service demands.” For many services “the primary value to the user is not necessarily strong consistency or durability, but rather high availability of data”. What such services can accept instead:

    1. Stale data “can be temporarily tolerated as long as all copies of data eventually reach consistency after a short time”.
    2. Soft state, “which can be generated at the expense of additional computation or file I/O, is exploited to improve performance; data is not durable”.
    3. Approximate answers “(based on stale data or incomplete soft state) delivered quickly may be more valuable than exact answers”.
    BASE[Fox et al., 1997]

    BASE: Basically Available, Soft state, Eventual consistency.

    Most cloud services nowadays adopt BASE, e.g. eBay and Amazon DynamoDB, and try to mask inconsistencies from users [Birman et al., 2012]. The slides note that Amazon S3 allows strong read-after-write consistency, and that DynamoDB writes are eventually consistent, reads too, but strongly consistent reads can be configured (at a higher cost). Steps ahead lead to new data-consistency models.

    Brewer [2012] sums up: “The modern CAP goal should be to maximise combinations of consistency and availability that make sense for the specific application. Such an approach incorporates plans for operation during a partition and for recovery afterward, thus helping designers think about CAP beyond its historically perceived limitations.” In Instrument 3, healing an AP partition reconciles concurrent writes by last-writer-wins.

    Lessons learnt · C1

    1. When the network fails, we typically have to choose between a responsive system and a fully consistent one.
    2. We can leverage CAP to design a system with different features depending on the overall system status.
    3. ACID is a thing to know and understand, yet less stringent models such as BASE can be both theoretically and practically useful in real-world distributed systems.

    For the oral

    The exam is a discussion of your project, so expect “why” questions rather than recitation. Practise answering these out loud in two minutes each.

    Why is “just replicate” not the answer?

    Copies drift once one is modified. Tight consistency needs every update applied atomically everywhere: global synchronisation, costing time, bandwidth and computation, and unavailable during partitions. When and how updates propagate is the real cost, plus machines and personnel.

    Why is W(x)1; R(y)0 ∥ W(y)1; R(x)0 causally but not sequentially consistent?

    Both reads returning 0 needs each read before the other's write: with program order, a cycle, so no interleaving. The writes are concurrent, so causally each process may see its own first.

    Give an example for each client-centric guarantee, and what breaks it.

    Vanishing e-mail (monotonic reads), library versions out of order (monotonic writes), new password rejected (read your writes), comment without its post (writes follow reads). Each breaks when the new replica lacks an update the client already saw or made.

    State CAP precisely. What exactly is impossible?

    In an asynchronous network, no read/write object guarantees both availability and atomic consistency in all fair executions, including those with message loss. Sketch α1 / α2 and indistinguishability.

    “Pick two of three”: why is that misleading?

    P is not a choice: networks partition, especially in IoT. C and A are spectra. Without a partition you get both [Brewer, 2012]. The question is what to do during a partition and how to recover.

    Project lens · Thunk
    Slide coverage: where each slide section went
    SlidesContentHere
    M3 · PrologueDisclaimer§1
    M3 · Why replication? I–IVReasons; benefits§1
    M3 · Issues I–IVCosts; consistency; Web caching§1
    M3 · Scaling technique I–VIN ≪ M; tight consistency; dilemma; relaxing§1
    M3 · ConsistencyModels; data first; data store; contract§2
    M3 · Data-centricContinuous; conit; ordering; sequential; causal§3
    M3 · Client-centricSwitching perspective; eventual consistency§4, §3
    M3 · Client-centricThe four guarantees§4
    M3 · ReplicationReplica, service, process replication§5
    M3 · More on replication I–IIBooks§5
    M3 · Fault tolerance? I–IITechnology table§5
    M3 · ConclusionLessons learnt§5
    C1 · Availability, consistency, failureHiding failure; safety vs liveness§6
    C1 · CAP at a glanceStatements; pick one I–II§6
    C1 · CAP at a glanceLocation-based games I–III§6
    C1 · Pokémon GoGoogle Cloud I–III§6
    C1 · Some proofOne way to see CAP (diagram); conjecture to theorem; C, A, P§7
    C1 · Some proofTheorem I–II; proof I–II§7
    C1 · Building on CAPImpossibility; switching strategy§8
    C1 · Building on CAPACID vs BASE; beyond BASE; CAP today§8
    C1 · ConclusionLessons learnt§8