Skip to content
back to the archive page
#DistributedSystems

The Tail at Scale: How to Beat the Slow Tail (#DistributedSystems)

In my notes on the 2013 whitepaper "The Tail at Scale," Monarch, Cassandra, QoS, and Harvest/Yield & the CAP theorem all came together. The paper connects these topics through one question: how do you respond quickly when an answer needs hundreds of servers, any of which may occasionally slow down?

Jeffrey Dean and Luiz André Barroso, both Google Fellows at the time, published it in Communications of the ACM in February 2013. They draw on Google's infrastructure experience: interactive search and distributed reads, where a rare delay on one node becomes a service-wide problem.

If each server takes longer than a second in 1% of cases, a request that waits for all 100 servers will be slow roughly 63% of the time. Basic probability: 1 − 0.99¹⁰⁰, assuming independent delays! My Monarch review, about Google's planet-scale telemetry system, covered another side of this problem: excluding irrelevant nodes before issuing the query.

The authors propose building tail-tolerant systems: predictably responsive services from components with unpredictable response times. Some of the resources are already there: replicas provisioned for fault tolerance. They can also help cope with delays.

What do they do about it?

🔸 Hedged requests If the first replica takes too long, send a copy to another; once a response arrives, cancel the rest. In a Google benchmark reading 1000 BigTable keys across 100 servers, hedging after 10 ms reduced the entire operation's p99.9 from 1800 to 74 ms with 2% more requests. That is a specific benchmark result; request count is not the same as CPU or disk consumption.

🔸Tied requests Enqueue copies in two queues; whichever starts execution first cancels its counterpart. Think of joining several airport queues and leaving the others as soon as you are called. This helps when waiting to start is the main source of delay. If execution itself is slow, the cancelled alternative might have been useful.

🔸 Small partitions and selective replication Divide the workload into more pieces than there are machines, move pieces between machines, and add replicas for popular data. This recalls Cassandra's virtual nodes. However, micro-partitioning is broader than consistent hashing, and evenly distributed data does not necessarily mean evenly distributed load.

There are familiar QoS techniques too: prioritizing interactive requests, keeping lower-level queues short, and splitting expensive operations. A less obvious suggestion is to sometimes synchronize background maintenance. With large fan-out, one short shared pause may affect fewer requests than different machines being busy all the time. But a shared pause can overload shared resources and build up a backlog.

Two more parallels from my notes: temporarily excluding a slow node resembles a circuit breaker, while testing a potentially dangerous request on a couple of servers before broadcasting it resembles a canary release at the request level.

Do we have to wait for everyone? For search, the authors allow occasionally returning a slightly incomplete result. That connects directly to Armando Fox and Eric Brewer's Harvest/Yield: answer completeness and the probability of completing a request. Their 1999 paper already states the CAP principle. I discussed guarantees in my lecture on CAP/PACELC and Cassandra at Central University. Completeness and consistency must be distinguished: skipping part of a search index and reading incompatible data versions are different problems.

Duplication has a boundary too: another replica needs a chance to respond faster. A shared overloaded resource or a request that is equally expensive everywhere can erase the benefit. Before adopting it, I would check where time is spent, how independent the alternative paths are, and what loss of answer quality the product can actually accept.

#DistributedSystems #Architecture #SystemDesign #SRE #Research

Files from the post

Public sources