Least-loaded routing
Why does routing to the least-loaded server oscillate, and how do two random choices fix it?
This is the purest example of gain with delay. A client that routes each request to the currently least-loaded server acts on a load number that is stale by the propagation delay d. All N clients read the same stale number in the same window, make the same decision, and herd onto the one empty server. It overloads before the number updates. Then they all move together to the next server. The oscillation period is about 2d, and total capacity use is poor, even though every single routing decision was optimal given its information.
Power of two choices
Power of two choices solves it: pick two servers at random and send the request to the less loaded of the two. The load imbalance improves from O(log N / log log N) to O(log log N): an exponential improvement. (These are growth rates: for 1,000,000 servers, log N / log log N is about 5 to 6, while log log N is about 3. The gap widens as N grows.) There is no global decision point and, importantly, no synchronization, because each client's random sample is independent.
- servers, or bins, receiving n items
Data table
| Servers n | series | Excess load (leading term) |
|---|---|---|
| 10 | one random choice | 2.76 |
| 12.6 | one random choice | 2.73 |
| 15.8 | one random choice | 2.72 |
| 20 | one random choice | 2.73 |
| 25.1 | one random choice | 2.75 |
| 31.6 | one random choice | 2.79 |
| 39.8 | one random choice | 2.83 |
| 50.1 | one random choice | 2.87 |
| 63.1 | one random choice | 2.92 |
| 79.4 | one random choice | 2.96 |
| 100 | one random choice | 3.02 |
| 126 | one random choice | 3.07 |
| 158 | one random choice | 3.12 |
| 200 | one random choice | 3.18 |
| 251 | one random choice | 3.23 |
| 316 | one random choice | 3.29 |
| 398 | one random choice | 3.35 |
| 501 | one random choice | 3.4 |
| 631 | one random choice | 3.46 |
| 794 | one random choice | 3.52 |
| 1K | one random choice | 3.57 |
| 1.26K | one random choice | 3.63 |
| 1.58K | one random choice | 3.69 |
| 2K | one random choice | 3.75 |
| 2.51K | one random choice | 3.8 |
| 3.16K | one random choice | 3.86 |
| 3.98K | one random choice | 3.92 |
| 5.01K | one random choice | 3.98 |
| 6.31K | one random choice | 4.03 |
| 7.94K | one random choice | 4.09 |
| 10K | one random choice | 4.15 |
| 12.6K | one random choice | 4.21 |
| 15.8K | one random choice | 4.26 |
| 20K | one random choice | 4.32 |
| 25.1K | one random choice | 4.38 |
| 31.6K | one random choice | 4.43 |
| 39.8K | one random choice | 4.49 |
| 50.1K | one random choice | 4.54 |
| 63.1K | one random choice | 4.6 |
| 79.4K | one random choice | 4.66 |
| 100K | one random choice | 4.71 |
| 126K | one random choice | 4.77 |
| 158K | one random choice | 4.82 |
| 200K | one random choice | 4.88 |
| 251K | one random choice | 4.93 |
| 316K | one random choice | 4.99 |
| 398K | one random choice | 5.04 |
| 501K | one random choice | 5.1 |
| 631K | one random choice | 5.15 |
| 794K | one random choice | 5.21 |
| 1M | one random choice | 5.26 |
| 1.26M | one random choice | 5.32 |
| 1.58M | one random choice | 5.37 |
| 2M | one random choice | 5.42 |
| 2.51M | one random choice | 5.48 |
| 3.16M | one random choice | 5.53 |
| 3.98M | one random choice | 5.58 |
| 5.01M | one random choice | 5.64 |
| 6.31M | one random choice | 5.69 |
| 7.94M | one random choice | 5.74 |
| 10M | one random choice | 5.8 |
| 12.6M | one random choice | 5.85 |
| 15.8M | one random choice | 5.9 |
| 20M | one random choice | 5.96 |
| 25.1M | one random choice | 6.01 |
| 31.6M | one random choice | 6.06 |
| 39.8M | one random choice | 6.11 |
| 50.1M | one random choice | 6.17 |
| 63.1M | one random choice | 6.22 |
| 79.4M | one random choice | 6.27 |
| 100M | one random choice | 6.32 |
| 126M | one random choice | 6.37 |
| 158M | one random choice | 6.43 |
| 200M | one random choice | 6.48 |
| 251M | one random choice | 6.53 |
| 316M | one random choice | 6.58 |
| 398M | one random choice | 6.63 |
| 501M | one random choice | 6.68 |
| 631M | one random choice | 6.73 |
| 794M | one random choice | 6.79 |
| 1B | one random choice | 6.84 |
| 10 | best of two | 1.2 |
| 12.6 | best of two | 1.34 |
| 15.8 | best of two | 1.47 |
| 20 | best of two | 1.58 |
| 25.1 | best of two | 1.69 |
| 31.6 | best of two | 1.79 |
| 39.8 | best of two | 1.88 |
| 50.1 | best of two | 1.97 |
| 63.1 | best of two | 2.05 |
| 79.4 | best of two | 2.13 |
| 100 | best of two | 2.2 |
| 126 | best of two | 2.27 |
| 158 | best of two | 2.34 |
| 200 | best of two | 2.4 |
| 251 | best of two | 2.47 |
| 316 | best of two | 2.53 |
| 398 | best of two | 2.58 |
| 501 | best of two | 2.64 |
| 631 | best of two | 2.69 |
| 794 | best of two | 2.74 |
| 1K | best of two | 2.79 |
| 1.26K | best of two | 2.84 |
| 1.58K | best of two | 2.88 |
| 2K | best of two | 2.93 |
| 2.51K | best of two | 2.97 |
| 3.16K | best of two | 3.01 |
| 3.98K | best of two | 3.05 |
| 5.01K | best of two | 3.09 |
| 6.31K | best of two | 3.13 |
| 7.94K | best of two | 3.17 |
| 10K | best of two | 3.2 |
| 12.6K | best of two | 3.24 |
| 15.8K | best of two | 3.27 |
| 20K | best of two | 3.31 |
| 25.1K | best of two | 3.34 |
| 31.6K | best of two | 3.37 |
| 39.8K | best of two | 3.4 |
| 50.1K | best of two | 3.44 |
| 63.1K | best of two | 3.47 |
| 79.4K | best of two | 3.5 |
| 100K | best of two | 3.53 |
| 126K | best of two | 3.55 |
| 158K | best of two | 3.58 |
| 200K | best of two | 3.61 |
| 251K | best of two | 3.64 |
| 316K | best of two | 3.66 |
| 398K | best of two | 3.69 |
| 501K | best of two | 3.71 |
| 631K | best of two | 3.74 |
| 794K | best of two | 3.76 |
| 1M | best of two | 3.79 |
| 1.26M | best of two | 3.81 |
| 1.58M | best of two | 3.84 |
| 2M | best of two | 3.86 |
| 2.51M | best of two | 3.88 |
| 3.16M | best of two | 3.9 |
| 3.98M | best of two | 3.93 |
| 5.01M | best of two | 3.95 |
| 6.31M | best of two | 3.97 |
| 7.94M | best of two | 3.99 |
| 10M | best of two | 4.01 |
| 12.6M | best of two | 4.03 |
| 15.8M | best of two | 4.05 |
| 20M | best of two | 4.07 |
| 25.1M | best of two | 4.09 |
| 31.6M | best of two | 4.11 |
| 39.8M | best of two | 4.13 |
| 50.1M | best of two | 4.15 |
| 63.1M | best of two | 4.17 |
| 79.4M | best of two | 4.19 |
| 100M | best of two | 4.2 |
| 126M | best of two | 4.22 |
| 158M | best of two | 4.24 |
| 200M | best of two | 4.26 |
| 251M | best of two | 4.27 |
| 316M | best of two | 4.29 |
| 398M | best of two | 4.31 |
| 501M | best of two | 4.32 |
| 631M | best of two | 4.34 |
| 794M | best of two | 4.36 |
| 1B | best of two | 4.37 |
This is the principle that randomization can replace coordination, and it is the clearest case yet. The randomness is not there to improve the estimate. It is there to destroy the correlation between clients. The cost: you never reach true least-loaded placement, which you could not have had anyway with stale data.
import random
def pick_server(servers, load):
a, b = random.sample(servers, 2)
return a if load[a] <= load[b] else b