Learn
Lesson · Partitioning and Load Balancing · Choosing the count

How Many Shards

There is no single formula for a shard count, because there are two constraints and each of them is a ceiling. Load asks for enough nodes that the peak rate divided among them sits under a target utilisation; storage asks for enough nodes that the dataset, multiplied by its replication factor, fits. You build the larger number, and the smaller one is the headroom you have in that dimension.

N_load = ⌈λ_peak / (c · ρ_target)⌉ c is ONE node's capacity N_storage = ⌈D · RF / per-node⌉ RF copies, not one N = max(N_load, N_storage) the other one is slack 120 000/(8 000 × 0.65) = 23.08 → 24 48 TB × 3 / 4 TB = 36.00 → 36
Two ceilings, and the one you actually build

Core ideas

What this lesson establishes

Both constraints are one division and one ceiling. What is new is that there are two of them and that the answer is a maximum rather than a sum.

1

Each constraint is a ceiling, not a division

120 000/(8 000 × 0.65) = 23.08 shards is not an answer, because a system cannot run 0.08 of a node. The ceiling is what makes the count buildable, and it is the reason a target utilisation of 65% produces a fleet that actually runs at 41.67% once the other constraint has had its say.

2

c is one node's capacity, never a count of nodes

In ⌈λ_peak/(c · ρ_target)⌉ the symbol c is requests a second that a single node can serve, and ρ_target is the fraction of that you are willing to use. Reading c as a machine count inverts the whole expression and gives an answer in the wrong units, which is a mistake that survives review because the number it produces still looks like a count.

3

The constraint that does not bind is your headroom

Two ceilings give two numbers and you build the larger, so one of them is always slack. That slack is worth reporting: at the defaults the fleet is sized by storage and each node is then running at 41.67% of its request capacity, which says exactly how much traffic growth the shard count already absorbs before anyone has to reshard.

The material

Two constraints, two ceilings, one count

What a shard is, the two questions that size a fleet of them, and why the answer is the larger of two numbers rather than either one of them.

Definition · Shard

A shard is a disjoint piece of a dataset, together with the node or nodes that serve it. Every key belongs to exactly one shard, and the rule that decides which is the partitioning function. A shard is not a replica: a replica is a copy of a piece, a shard is a piece. Splitting is this course; copying is “Replication and Consistency”.

Two independent questions decide how many shards you build, and they are asked of different resources. The first is about throughput: how many nodes does it take for the peak request rate, divided among them, to sit under the utilisation you are willing to run at? The second is about bytes: how many nodes does it take to hold the dataset once every item has been written RF times?

load N_load = ⌈ λ_peak / (c · ρ_target) ⌉ storage N_storage = ⌈ D · RF / per-node ⌉ the count N = max(N_load, N_storage) λ_peak = 120 000 /s c = 8 000 /s ρ_target = 0.65 D = 48 TB RF = 3 per-node = 4 TB N_load = ⌈ 120 000 / 5 200 ⌉ = ⌈ 300/13 ⌉ = ⌈ 23.08 ⌉ = 24 N_storage = ⌈ 144 TB / 4 TB ⌉ = ⌈ 36.00 ⌉ = 36 N = max(24, 36) = 36

The RF in the storage line is the whole of that constraint. A 48 TB dataset at three copies is 144 TB of stored bytes, and it is the 144 that has to fit. Dropping the factor gives 12 shards instead of 36 — a fleet a third the size, sized against a number that never existed on any disk.

Example · The same fleet, one constraint at a time

At the numbers above, load asks for 24 and storage asks for 36, so you build 36 and storage binds by 12 shards. Hold the storage figures and take the peak to 200 000 /s: load now asks for ⌈200 000/5 200⌉ = ⌈38.46⌉ = 39, storage still asks for 36, and load binds by 3. Hold the load figures and take the dataset to 20 TB: storage asks for ⌈60/4⌉ = 15 and load binds by 9. Nothing about the method changed; which constraint won changed twice.

What the slack tells you, and what no slack tells you

At 36 shards each node serves 120 000/36 = 3 333 /s against a capacity of 8 000 /s, which is 41.67% — well under the 65% target that produced the load ceiling. Request traffic could grow by more than half before load starts to bind, and that is a real answer to “when do we reshard?”.

Storage at the same count has no slack at all. Each node holds 144 TB/36 = 4.00 TB of a 4 TB node, because the storage ceiling happened to land on a whole number. A dataset that grows by one byte adds a shard, and the lab shows this by moving the dataset slider a single terabyte. A ceiling that comes out exact is the least comfortable answer this arithmetic can give.

Where the load ceiling came from

The load line is not new. “From a Request's Cost to a Machine Count” derives it from one request's cost and one machine's capacity, and everything this lesson adds is the second constraint and the maximum. If the utilisation target in it looks arbitrary, “The Knee: Response Time vs Utilisation” is where the number comes from: the wait rises without bound as ρ approaches 1, so the target is chosen on the flat part of that curve and then divided into.

Both ceilings are computed as exact fractions in the lab and rounded only at the ceiling itself, which matters more than it sounds: 300/13 is 23.076923…, and a calculation that rounds to 23.1 before taking the ceiling still gives 24, while one that rounds to 23 gives 23 and under-provisions the fleet by a node.

Interactive

How many shards

Load gives one count, storage gives another, and you build the larger

Two constraints, one countload gives one number, storage gives another, and the answer is the larger
from loadfrom storagethe binding one

Method

Sizing a fleet on two constraints

Four lines. Only the third and fourth are arithmetic; the first two are what stop the arithmetic being done on the wrong quantity.

1

Write the peak rate, not the average

The count is sized on λ_peak. An average rate with a peak-to-average ratio of three in front of it will size a fleet that falls over daily, and “Peak to Average” is where that ratio comes from.

2

Divide by one node's capacity and by the utilisation target

c · ρ_target is the rate you are actually willing to take from one node. Divide the peak by it and take the ceiling. Carrying the division as an exact fraction until the ceiling is what keeps 23.08 from becoming 23.

3

Multiply the dataset by the replication factor first

D · RF is the bytes that exist, and that is what has to fit on the nodes you buy. Divide by one node's usable capacity and take the ceiling again. Usable, not nominal: whatever the filesystem, the index and the compaction headroom take is not available to store the data.

4

Take the maximum, and report the slack in the other one

One number is the answer and the other is headroom. Say both: “36 shards, sized by storage; load then runs at 41.67% of capacity” is an answer someone can plan against, and “36 shards” alone is not.

Two ceilings and a maximum

Score 0 / 0

48 TB at three copies, 120 000 requests a second

Both ceilings, then the maximum, then what the loser of the two is worth as headroom.

load usable rate a node = c · ρ_target = 8 000 × 0.65 = 5 200 /s N_load = ⌈ 120 000 / 5 200 ⌉ = ⌈ 300/13 ⌉ = ⌈ 23.0769… ⌉ = 24 storage bytes that exist = D · RF = 48 TB × 3 = 144 TB N_storage = ⌈ 144 / 4 ⌉ = ⌈ 36.00 ⌉ = 36 the count N = max(24, 36) = 36 storage binds, by 12 shards what the fleet then looks like each node serves 120 000/36 = 3 333.3 /s of 8 000 /s = 41.67% each node holds 144/36 = 4.00 TB of 4 TB = 100%

The last two lines are the ones worth keeping. The fleet was sized by storage, so storage is full and load is half idle, and those two facts together say which way this system will break: not under a traffic spike, but on the day the dataset grows.

For a faded rehearsal, hold c = 8 000 /s, ρ_target = 0.65, per-node = 4 TB and RF = 3, and take the peak to 260 000 /s with the dataset at 60 TB. The supplied first move is the usable rate a node, which is unchanged at 5 200 /s. Produce both ceilings, say which binds and by how much, and then state the utilisation each node runs at under the count you chose. Check all three in the lab before opening the quiz.

Common mistakes

1
Sizing on one constraint and meeting the other in productionA fleet sized on load alone runs out of disk and a fleet sized on storage alone runs out of throughput, and in both cases the number that was computed was correct. Compute both, always, and write the loser down beside the winner — it is the only record of how much room you have.
2
Dropping the replication factor from the storage lineThe bytes that have to fit are D · RF, not D. At three copies the difference is a factor of three in the fleet size, and the error is easy to make because the dataset is the number everybody quotes and the replication factor lives in a different team's configuration.
3
Rounding before the ceiling instead of at it300/13 is 23.0769…; rounded to 23 it under-provisions, and rounded to 23.1 it does not, because the ceiling comes last. Carry the division exact and apply ⌈·⌉ once, at the end. The lab keeps both constraints as fractions for exactly this reason.

Check your understanding

✓
Finish when “how many shards?” is two questions to you rather than one.

You should be able to produce both ceilings from a description of a workload, say which binds, state the utilisation and the bytes per node that the chosen count implies, and name what the slack in the other constraint buys.

Note: Having chosen N, the next question is what happens when it changes, and the answer is worse than most people expect: under a plain mod N assignment, going from N to N + 1 relocates nearly every key in the system. “Rehashing When N Changes” counts exactly how many.

Kept in this browser only, for you. Nothing is sent anywhere and nothing checks it. Carry it to another device.

Feedback and recommendations

Something to change about this lesson? Write it down, tick it off when it is handled, and export the list when you want to act on it. Kept in this browser only: nothing is sent anywhere, and nobody is notified.

No recommendations yet for this lesson.