The idea: know who is alive without a central server

A cluster of a few to a few thousand machines needs a membership list: who is in the cluster, and who has died. A central server that pings everyone is a bottleneck and a single point of failure, and having everyone ping everyone costs N² messages. Gossip protocols spread news the way a rumor spreads: each member tells a few random others, who tell a few more. SWIM (Scalable Weakly-consistent Infection-style Membership, Das, Gupta and Motivala, 2002) builds failure detection on top: each member checks one random member per period, and news about failures rides on those checks.

Push gossip with fanout 2 on 8 members, as in Demo 1: round 0, only N1 has x=1; round 1, N1 pushes to N2 and N4, 3 members have it; round 2, 6 pushes reach 4 new members, 2 are duplicates, 7 have it; round 3, N6 reaches N3, the last one, while 13 of the 14 pushes are duplicates.
Each member that has the update pushes it to 2 random peers per round, so the count grows by a factor each round and 8 members need about 3 rounds.
On the pageMeaning
circles N1 to N9what is really true: grey-blue alive, yellow has the rumor, grey ✗ crashed, purple frozen in a GC pause, faded N9 not a member yet; inc is the member's own incarnation number
membership viewsrow N3 is what N3 believes about every member: A0 alive with incarnation 0, S0·2 suspect with 2 periods left, D0 dead; the diagonal is the member itself
piggyback columnthe updates a member still has to pass on, with the sends left: N5?×3
message boxesping, ack, ping-req, followed by the updates they carry: N5? suspect, N5✓ alive, N5✗ dead, N9+ joined
gossip charthow many members have the rumor after each round

Push gossip and log N rounds

In push gossip a member with a new update sends it to fanout peers picked at random (2 here; memberlist's GossipNodes is 3). Every member that receives it does the same in the next round. While few members have it, almost every push reaches someone new, so the number of informed members multiplies each round; N members are covered in about log N rounds (8 members: about 3), and the protocol tolerates lost messages and crashed members without any coordination (Demo 1).

The price is duplicates: near the end most pushes go to members that already have the update, and the senders cannot know that. Each member therefore pushes for a limited number of rounds (3 here) and then stops. A member can still be missed by bad luck, so real systems add a slower anti-entropy sync that compares full state now and then (memberlist's push-pull every 30 seconds; see Merkle Trees and Anti-Entropy).

SWIM: ping, ack and ping-req

SWIM divides time into protocol periods (memberlist's ProbeInterval, 1 second). In each period every member picks one member and sends it a ping; the target answers ack. Each member sends one ping per period, so the load stays constant however large the cluster is. The page picks targets with one random shift per period, so every member is also pinged exactly once.

A missing ack does not prove much: the target may be fine and only the path between the two members slow or lossy. So the prober sends ping-req to k other members (k = 2 here; IndirectChecks = 3), and each of them pings the target and forwards the ack. Only if none of these paths gets an ack before the period ends does the prober suspect the target (Demo 3: a slow link between N1 and N4 alone does not get N4 suspected).

Time runs down for four members N2, N1, N4 and N3. N1 pings N4 over a slow link and the ping misses the timeout. N1 sends ping-req N4 to N2 and N3. Each pings N4, N4 acks each, and they forward the ack to N1 before the period ends.
The direct ping is lost, but two helpers reach the target over other paths, so the prober gets its ack within the same period.

Suspect, dead and incarnation numbers

The original SWIM paper declared a member dead as soon as the indirect probe failed. A member that is only slow for a moment (a long garbage-collection pause, a full network buffer) was then thrown out. The improved version marks it suspect first and starts a suspicion timeout (3 periods here; memberlist uses SuspicionMult · log N periods). If nobody refutes the suspicion in time, it becomes dead, and that is final for this incarnation (Demo 2).

Each member owns an incarnation number that only it may raise. When a member hears that it is suspected, it increments its incarnation and spreads alive with the new number. The rules decide which news wins: newer incarnation beats older, and at the same incarnation suspect beats alive and dead beats both (Demo 4: N7 is suspected during a GC pause and refutes it with incarnation 1).

A member receivesIt replaces the entry when
alive, incarnation ithe entry has an incarnation lower than i
suspect, incarnation ialive with incarnation ≤ i, or suspect with incarnation < i
dead, incarnation ialive or suspect with incarnation ≤ i
suspect or dead about itselfnever; it refutes: incarnation = i + 1 and it spreads alive
Three snapshots of how N4 sees N7 in Demo 4. First A0, alive with incarnation 0. Then S0, suspect, after no ack and no indirect ack in period 1. Then A1 after N7 refutes: alive with incarnation 1 overrides suspect with incarnation 0. A late suspect message with incarnation 0 is then ignored.
Only N7 can raise its own incarnation, so alive #1 overrides every older suspicion and a late suspect #0 changes nothing.

Piggybacking membership changes

SWIM sends no separate messages for news. Every member keeps a small buffer of recent updates (N5 suspect, N7 alive #1, N9 joined) and attaches a few of them to every ping and ack it sends anyway. Each update is sent about λ·log N times (4 here; memberlist's RetransmitMult · log(N+1)) and then dropped. Since pings go to random members, the news spreads exactly like gossip, in O(log N) periods, at zero extra message cost. Watch the piggyback column: counts go down with each send, and a member that learns something new adds it to its own buffer.

Joining

A new node needs the address of one member, the seed. It sends a join to the seed, the seed answers with its full membership list and starts piggybacking N9+; the rest of the cluster learns about the new member over the next few periods (Demo 5). Leaving works the same way with a "left" update, so the member is not mistaken for a failure.

Where it is used

HashiCorp memberlist (behind Consul and Serf, and Nomad) is SWIM with the suspicion and incarnation rules shown here plus Lifeguard, which lengthens timeouts on a member that sees itself missing acks. Cassandra and ScyllaDB gossip node state once a second with three random peers. Redis Cluster nodes ping each other on the cluster bus and mark a master PFAIL, then FAIL when a majority agrees, which is the same suspect-then-confirm idea. Gossip spreads membership, but it does not give agreement: for one leader or one log order, see Raft and Leader Election.

See also Consistent Hashing (what a membership list is used for), CRDTs (data that merges cleanly however gossip delivers it), Lamport and Vector Clocks and The CAP Theorem.

What the page leaves out

Real members ping a target from their own shuffled list, round-robin, so a member can be pinged several times in one period; the page uses one shift for everybody so every member is pinged once. Messages are UDP packets with a timeout inside the period, and the indirect ping has its own shorter timeout; the page counts a slow link as simply lost. Only pings and acks carry updates here (real SWIM piggybacks on ping-req too), at most 2 per message. Lifeguard's dynamic timeouts and the "suspicion confirmations" that shorten a timeout, the periodic push-pull full-state sync, graceful leave, TCP fallback pings, encryption and the network-coordinate (Vivaldi) data that memberlist also gossips are left out. Each member's suspicion timer is counted in whole periods, and a member's own timers stop while it is crashed or paused.