Task re-execution and blacklisting
Why does a large job need re-execution to finish at all, and what does blacklisting a node cost?
What it is. At job scale, failure stops being rare. Take a batch job with n = 10⁴ tasks, each with failure probability p = 10⁻³. The probability that no task fails is
(1 − p)ⁿ ≈ e⁻¹⁰ ≈ 4.5 × 10⁻⁵.
(Check: n × p = 10⁴ × 10⁻³ = 10, and (1 − p)ⁿ ≈ e^(−np) = e⁻¹⁰.) A job of this size almost always contains a failure. Job-level success is not something you can buy from reliable parts. It must be manufactured by re-execution. This is why batch engines have retry built in, while a single-process program does not: the same p that is negligible at n = 10 is certain at n = 10⁴. It is Wanjiru's billing-rollup.
Re-executing a failed task up to k times changes the formula from (1 − p)ⁿ to (1 − pᵏ)ⁿ. With k = 3: pᵏ = 10⁻⁹, so (1 − 10⁻⁹)^10,000 ≈ 1 − 10⁻⁵, nearly 1. This works only if attempts are independent, the third time this article has depended on that condition.
- tasks in the job
- failure probability of one task attempt
- attempts allowed per task
Data table
| Tasks n | series | P(job succeeds) |
|---|---|---|
| 10 | no retry (k = 1) | 0.99 |
| 11.9 | no retry (k = 1) | 0.988 |
| 14.1 | no retry (k = 1) | 0.986 |
| 16.8 | no retry (k = 1) | 0.983 |
| 20 | no retry (k = 1) | 0.98 |
| 23.7 | no retry (k = 1) | 0.977 |
| 28.2 | no retry (k = 1) | 0.972 |
| 33.5 | no retry (k = 1) | 0.967 |
| 39.8 | no retry (k = 1) | 0.961 |
| 47.3 | no retry (k = 1) | 0.954 |
| 56.2 | no retry (k = 1) | 0.945 |
| 66.8 | no retry (k = 1) | 0.935 |
| 79.4 | no retry (k = 1) | 0.924 |
| 94.4 | no retry (k = 1) | 0.91 |
| 112 | no retry (k = 1) | 0.894 |
| 133 | no retry (k = 1) | 0.875 |
| 158 | no retry (k = 1) | 0.853 |
| 188 | no retry (k = 1) | 0.828 |
| 224 | no retry (k = 1) | 0.799 |
| 266 | no retry (k = 1) | 0.766 |
| 316 | no retry (k = 1) | 0.729 |
| 376 | no retry (k = 1) | 0.687 |
| 447 | no retry (k = 1) | 0.64 |
| 531 | no retry (k = 1) | 0.588 |
| 631 | no retry (k = 1) | 0.532 |
| 750 | no retry (k = 1) | 0.472 |
| 891 | no retry (k = 1) | 0.41 |
| 1.06K | no retry (k = 1) | 0.347 |
| 1.26K | no retry (k = 1) | 0.284 |
| 1.5K | no retry (k = 1) | 0.224 |
| 1.78K | no retry (k = 1) | 0.169 |
| 2.11K | no retry (k = 1) | 0.121 |
| 2.51K | no retry (k = 1) | 0.081 |
| 2.99K | no retry (k = 1) | 0.05 |
| 3.55K | no retry (k = 1) | 0.029 |
| 4.22K | no retry (k = 1) | 0.015 |
| 5.01K | no retry (k = 1) | 0.007 |
| 5.96K | no retry (k = 1) | 0.003 |
| 7.08K | no retry (k = 1) | 0.001 |
| 8.41K | no retry (k = 1) | 0 |
| 10K | no retry (k = 1) | 0 |
| 11.9K | no retry (k = 1) | 0 |
| 14.1K | no retry (k = 1) | 0 |
| 16.8K | no retry (k = 1) | 0 |
| 20K | no retry (k = 1) | 0 |
| 23.7K | no retry (k = 1) | 0 |
| 28.2K | no retry (k = 1) | 0 |
| 33.5K | no retry (k = 1) | 0 |
| 39.8K | no retry (k = 1) | 0 |
| 47.3K | no retry (k = 1) | 0 |
| 56.2K | no retry (k = 1) | 0 |
| 66.8K | no retry (k = 1) | 0 |
| 79.4K | no retry (k = 1) | 0 |
| 94.4K | no retry (k = 1) | 0 |
| 112K | no retry (k = 1) | 0 |
| 133K | no retry (k = 1) | 0 |
| 158K | no retry (k = 1) | 0 |
| 188K | no retry (k = 1) | 0 |
| 224K | no retry (k = 1) | 0 |
| 266K | no retry (k = 1) | 0 |
| 316K | no retry (k = 1) | 0 |
| 376K | no retry (k = 1) | 0 |
| 447K | no retry (k = 1) | 0 |
| 531K | no retry (k = 1) | 0 |
| 631K | no retry (k = 1) | 0 |
| 750K | no retry (k = 1) | 0 |
| 891K | no retry (k = 1) | 0 |
| 1.06M | no retry (k = 1) | 0 |
| 1.26M | no retry (k = 1) | 0 |
| 1.5M | no retry (k = 1) | 0 |
| 1.78M | no retry (k = 1) | 0 |
| 2.11M | no retry (k = 1) | 0 |
| 2.51M | no retry (k = 1) | 0 |
| 2.99M | no retry (k = 1) | 0 |
| 3.55M | no retry (k = 1) | 0 |
| 4.22M | no retry (k = 1) | 0 |
| 5.01M | no retry (k = 1) | 0 |
| 5.96M | no retry (k = 1) | 0 |
| 7.08M | no retry (k = 1) | 0 |
| 8.41M | no retry (k = 1) | 0 |
| 10M | no retry (k = 1) | 0 |
| 10 | k = 2 | 1 |
| 11.9 | k = 2 | 1 |
| 14.1 | k = 2 | 1 |
| 16.8 | k = 2 | 1 |
| 20 | k = 2 | 1 |
| 23.7 | k = 2 | 1 |
| 28.2 | k = 2 | 1 |
| 33.5 | k = 2 | 1 |
| 39.8 | k = 2 | 1 |
| 47.3 | k = 2 | 1 |
| 56.2 | k = 2 | 1 |
| 66.8 | k = 2 | 1 |
| 79.4 | k = 2 | 1 |
| 94.4 | k = 2 | 1 |
| 112 | k = 2 | 1 |
| 133 | k = 2 | 1 |
| 158 | k = 2 | 1 |
| 188 | k = 2 | 1 |
| 224 | k = 2 | 1 |
| 266 | k = 2 | 1 |
| 316 | k = 2 | 1 |
| 376 | k = 2 | 1 |
| 447 | k = 2 | 1 |
| 531 | k = 2 | 0.999 |
| 631 | k = 2 | 0.999 |
| 750 | k = 2 | 0.999 |
| 891 | k = 2 | 0.999 |
| 1.06K | k = 2 | 0.999 |
| 1.26K | k = 2 | 0.999 |
| 1.5K | k = 2 | 0.999 |
| 1.78K | k = 2 | 0.998 |
| 2.11K | k = 2 | 0.998 |
| 2.51K | k = 2 | 0.997 |
| 2.99K | k = 2 | 0.997 |
| 3.55K | k = 2 | 0.996 |
| 4.22K | k = 2 | 0.996 |
| 5.01K | k = 2 | 0.995 |
| 5.96K | k = 2 | 0.994 |
| 7.08K | k = 2 | 0.993 |
| 8.41K | k = 2 | 0.992 |
| 10K | k = 2 | 0.99 |
| 11.9K | k = 2 | 0.988 |
| 14.1K | k = 2 | 0.986 |
| 16.8K | k = 2 | 0.983 |
| 20K | k = 2 | 0.98 |
| 23.7K | k = 2 | 0.977 |
| 28.2K | k = 2 | 0.972 |
| 33.5K | k = 2 | 0.967 |
| 39.8K | k = 2 | 0.961 |
| 47.3K | k = 2 | 0.954 |
| 56.2K | k = 2 | 0.945 |
| 66.8K | k = 2 | 0.935 |
| 79.4K | k = 2 | 0.924 |
| 94.4K | k = 2 | 0.91 |
| 112K | k = 2 | 0.894 |
| 133K | k = 2 | 0.875 |
| 158K | k = 2 | 0.853 |
| 188K | k = 2 | 0.828 |
| 224K | k = 2 | 0.799 |
| 266K | k = 2 | 0.766 |
| 316K | k = 2 | 0.729 |
| 376K | k = 2 | 0.687 |
| 447K | k = 2 | 0.64 |
| 531K | k = 2 | 0.588 |
| 631K | k = 2 | 0.532 |
| 750K | k = 2 | 0.472 |
| 891K | k = 2 | 0.41 |
| 1.06M | k = 2 | 0.347 |
| 1.26M | k = 2 | 0.284 |
| 1.5M | k = 2 | 0.224 |
| 1.78M | k = 2 | 0.169 |
| 2.11M | k = 2 | 0.121 |
| 2.51M | k = 2 | 0.081 |
| 2.99M | k = 2 | 0.051 |
| 3.55M | k = 2 | 0.029 |
| 4.22M | k = 2 | 0.015 |
| 5.01M | k = 2 | 0.007 |
| 5.96M | k = 2 | 0.003 |
| 7.08M | k = 2 | 0.001 |
| 8.41M | k = 2 | 0 |
| 10M | k = 2 | 0 |
| 10 | k = 3 | 1 |
| 11.9 | k = 3 | 1 |
| 14.1 | k = 3 | 1 |
| 16.8 | k = 3 | 1 |
| 20 | k = 3 | 1 |
| 23.7 | k = 3 | 1 |
| 28.2 | k = 3 | 1 |
| 33.5 | k = 3 | 1 |
| 39.8 | k = 3 | 1 |
| 47.3 | k = 3 | 1 |
| 56.2 | k = 3 | 1 |
| 66.8 | k = 3 | 1 |
| 79.4 | k = 3 | 1 |
| 94.4 | k = 3 | 1 |
| 112 | k = 3 | 1 |
| 133 | k = 3 | 1 |
| 158 | k = 3 | 1 |
| 188 | k = 3 | 1 |
| 224 | k = 3 | 1 |
| 266 | k = 3 | 1 |
| 316 | k = 3 | 1 |
| 376 | k = 3 | 1 |
| 447 | k = 3 | 1 |
| 531 | k = 3 | 1 |
| 631 | k = 3 | 1 |
| 750 | k = 3 | 1 |
| 891 | k = 3 | 1 |
| 1.06K | k = 3 | 1 |
| 1.26K | k = 3 | 1 |
| 1.5K | k = 3 | 1 |
| 1.78K | k = 3 | 1 |
| 2.11K | k = 3 | 1 |
| 2.51K | k = 3 | 1 |
| 2.99K | k = 3 | 1 |
| 3.55K | k = 3 | 1 |
| 4.22K | k = 3 | 1 |
| 5.01K | k = 3 | 1 |
| 5.96K | k = 3 | 1 |
| 7.08K | k = 3 | 1 |
| 8.41K | k = 3 | 1 |
| 10K | k = 3 | 1 |
| 11.9K | k = 3 | 1 |
| 14.1K | k = 3 | 1 |
| 16.8K | k = 3 | 1 |
| 20K | k = 3 | 1 |
| 23.7K | k = 3 | 1 |
| 28.2K | k = 3 | 1 |
| 33.5K | k = 3 | 1 |
| 39.8K | k = 3 | 1 |
| 47.3K | k = 3 | 1 |
| 56.2K | k = 3 | 1 |
| 66.8K | k = 3 | 1 |
| 79.4K | k = 3 | 1 |
| 94.4K | k = 3 | 1 |
| 112K | k = 3 | 1 |
| 133K | k = 3 | 1 |
| 158K | k = 3 | 1 |
| 188K | k = 3 | 1 |
| 224K | k = 3 | 1 |
| 266K | k = 3 | 1 |
| 316K | k = 3 | 1 |
| 376K | k = 3 | 1 |
| 447K | k = 3 | 1 |
| 531K | k = 3 | 0.999 |
| 631K | k = 3 | 0.999 |
| 750K | k = 3 | 0.999 |
| 891K | k = 3 | 0.999 |
| 1.06M | k = 3 | 0.999 |
| 1.26M | k = 3 | 0.999 |
| 1.5M | k = 3 | 0.999 |
| 1.78M | k = 3 | 0.998 |
| 2.11M | k = 3 | 0.998 |
| 2.51M | k = 3 | 0.997 |
| 2.99M | k = 3 | 0.997 |
| 3.55M | k = 3 | 0.996 |
| 4.22M | k = 3 | 0.996 |
| 5.01M | k = 3 | 0.995 |
| 5.96M | k = 3 | 0.994 |
| 7.08M | k = 3 | 0.993 |
| 8.41M | k = 3 | 0.992 |
| 10M | k = 3 | 0.99 |
Blacklisting restores independence
When failures cluster on one node (a bad disk, a bad network card), retrying on the same node gives dependent attempts. Retrying elsewhere makes them independent again. So blacklisting (excluding a node from scheduling) is an online classifier that decides which failures are caused by the node. Like every classifier working on little evidence, it has two errors with different costs:
- Blacklist a healthy node: you lose capacity. Under broad, load-induced failure you can blacklist the entire fleet, a real and spectacular production outcome.
- Fail to blacklist a sick node: tasks keep landing on it, and the retry count is consumed by the same fault.
So every implementation has decay on entries (a node returns after some time), a quota (never exclude more than a fraction), and a scope decision (per stage or per application). Structurally this is the same object as a failure detector: a guess with unequal costs and no ground truth.
The unit of failure is not the unit of retry
Re-executing a task recovers a task. But losing an executor (a worker process) loses its cached blocks and its shuffle files too, so other tasks' completed work dies with it. The cost is greater than linear in the size of the failure. This repeats at every level: container, node, availability zone (a separate data centre building within a region).
Not covered here. Speculative execution (starting a second copy of a slow task) treats slowness rather than failure and is a different model. The record that kills every attempt is the poison pill of Making a repeat harmless.