Splitting data across machines
Partitioning, also called sharding, splits one big data set into parts and puts each part on a different machine. A shop with 100 million customers cannot keep them all on one disk.
You will learn how a key decides which machine holds a record, and why the first obvious method breaks when you add a machine.
By the end of this lesson
Note
I can split data across machines by key.
Key words
| Word | What it means | Example |
|---|---|---|
| Partition | one part of a split data set | shard |
| Key | the name that picks a record | ada |
| Hash function | a rule that turns a key into a number | |
| Remainder | what is left after dividing | 10 % 3 is 1 |
| Ring | positions that wrap round from the end to the start | |
| Hot spot | one partition that gets far more work |
The cells students fill in are left blank in this preview.
A key decides which machine holds a record
Replication copies all the data to each machine. Partitioning is different: each machine holds only part of it, so the whole set can be bigger than any one disk.
The system needs a rule that tells every machine where a record lives, using only its key. A simple rule: turn the key into a number with a hash function, then take the remainder after dividing by the number of machines.
Hash a key, then take the remainder
# The lesson's hash: add up the codes of the letters.
def key_hash(key):
total = 0
for letter in key:
total = total + ord(letter)
return total
for key in ["ada", "bo", "cy", "dee"]:
number = key_hash(key)
print(key, number, "goes to machine", number % 3)
# Change 3 to 4 and run again: most keys move.
Worked example: eight keys on three machines
| Key | Hash | Remainder after 3 | Remainder after 4 |
|---|---|---|---|
| ada | 294 | 0 | 2 |
| bo | 209 | 2 | 1 |
| cy | 220 | 1 | 0 |
| dee | 302 | 2 | 2 |
| eli | 314 | 2 | 2 |
| fay | 320 | 2 | 0 |
| gus | 335 | 2 | 3 |
| hal | 309 | 0 | 1 |
The cells students fill in are left blank in this preview.
Adding a machine moves most of the keys
The remainder rule has a bad habit. Look at the last two columns of the table. Going from three machines to four changes the machine for six of the eight keys.
Moving data across the network is slow and loads every machine. Adding one machine should move about a quarter of the keys, not most of them.
Count the keys that move
# How many of eight keys change machine when a fourth machine arrives?
def key_hash(key):
total = 0
for letter in key:
total = total + ord(letter)
return total
keys = ["ada", "bo", "cy", "dee", "eli", "fay", "gus", "hal"]
moved = 0
for key in keys:
if key_hash(key) % 3 != key_hash(key) % 4:
moved = moved + 1
print(moved, "of", len(keys), "keys moved")
Consistent hashing moves only a few keys
In consistent hashing the hash numbers are placed on a ring: positions 0 to 359 that wrap round. Each machine is given a position too.
A key goes to the first machine at or after its position, going round. Past the highest machine it wraps to the lowest. A new machine takes keys only from the stretch just before it.
Worked example: adding machine D at 310
| Key | Position | Owner with A, B, C | Owner after D is added |
|---|---|---|---|
| ada | 294 | C | D |
| bo | 209 | B | B |
| cy | 220 | B | B |
| dee | 302 | C | D |
| eli | 314 | C | C |
| fay | 320 | C | C |
| gus | 335 | A | A |
| hal | 309 | C | D |
The cells students fill in are left blank in this preview.
Make a tiny client called v
v() ( printf '%s\r\n' "$*" | nc -w 1 valkey 6379 )Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Ask whether this store is split over machines
v INFO cluster | grep cluster_enabledShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Store three carts in one command
v MSET cart:ada 2 cart:bo 5 cart:cy 1Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Count how many of three keys exist
v EXISTS cart:ada cart:bo cart:cyShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people think a hash always spreads the work evenly. It spreads keys, not requests. If one key is far busier than the rest, such as a famous shop's cart, its machine takes all that traffic. That machine is a hot spot.
A split store cannot do everything at once
The command that stored three carts at once is easy on one machine. If the three keys sit on three machines, no single machine can do it in one step.
So partitioned stores limit commands that touch many keys. Or they ask you to give related keys a shared part of their name, so that they land together.