Chapter 03 · Partitioners, Tokens, Vnodes, Token Rings, and Data Distribution

Partition Key Hashing and Murmur3Partitioner: From Key to Token

Follow one AtlasMart partition key from application value to Murmur3 token and replica placement, and learn why hashing cannot rescue a bad key design.

Intermediate105–130 minutesMurmur3 key-to-token evidence labApache Cassandra 5.0.9 · Murmur3 · 16 vnodes/nodeLast reviewed: September 2026

Learning outcomes

AtlasMart has three healthy Cassandra nodes, but “three nodes” says nothing about where a particular product partition lives. Cassandra first transforms the table's partition key into a token; only then can token ownership and the keyspace replication strategy determine the replicas. This lesson makes that transformation observable before the course talks about ring diagrams or scaling.

01

Explain the difference between a primary key, partition key, serialized partition-key value, token, token range, and physical node.

02

Explain why Murmur3Partitioner intentionally destroys lexical/monotonic ordering of ordinary partition-key values.

03

Use CQL token() to map deterministic AtlasMart keys to bigint tokens and compare repeatability.

04

Trace a token from the partitioner to natural replicas without treating the contacted node as the owner by definition.

05

Identify low-cardinality and constant partition keys as schema problems that hashing cannot repair.

Chapter baseline reviewed 7 September 2026

Apache Cassandra 5.0.9 is the current GA 5.0 patch on the official download page. The labs pin cassandra:5.0.9 and explicitly set CASSANDRA_NUM_TOKENS=16 so vnode behavior is reproducible instead of inheriting an unnoticed image/configuration default. Current Cassandra 5.0 documentation uses num_tokens: 16 as the modern baseline; older Cassandra material often mentions 256 random vnodes, so this chapter treats token count as a version- and deployment-sensitive design choice rather than folklore.

Execution and evidence note

The generation environment does not contain Docker or Cassandra, so Cassandra commands were checked against current official documentation but were not executed here. Exact token values, IP addresses, host IDs, ownership percentages, load, stream sizes, latency, and hot-partition samples must be captured on the learner's machine. Expected output is described as invariants or shapes, never presented as measured output.

1. Partition keys choose distribution; clustering keys do not

In Cassandra, a table's primary key can contain two logical pieces. The partition key identifies the partition and is the input to the partitioner. Optional clustering columns order rows inside that partition. For products_by_id, product_id is the whole primary key and therefore the whole partition key. Later query-first tables may use a composite partition key such as (customer_id, month_bucket); Cassandra hashes the serialized combination, not each component independently.

The default modern partitioner is org.apache.cassandra.dht.Murmur3Partitioner. It maps a partition-key value to a token represented by CQL as a bigint. Hashing is deterministic: the same correctly serialized key under the same partitioner maps to the same token. It is also deliberately distribution-oriented: nearby strings such as p-1001 and p-1002 do not have to produce nearby tokens.

Hashing cannot create cardinality.

If every AtlasMart request uses the partition key 'global', Murmur3 hashes that one value to one token. Adding servers creates more token owners elsewhere, but the global partition still maps to the same token and its replicas.

2. Observe the active partitioner before trusting a diagram

bash / PowerShell · reproducible 3-node, 16-vnode lab
docker network create atlasmart-cassandradocker volume create atlasmart-cass-1-datadocker volume create atlasmart-cass-2-datadocker volume create atlasmart-cass-3-datadocker run -d --name atlasmart-cass-1 --hostname atlasmart-cass-1 --network atlasmart-cassandra -e CASSANDRA_CLUSTER_NAME=atlasmart-course -e CASSANDRA_DC=dc1 -e CASSANDRA_RACK=rack1 -e CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch -e CASSANDRA_NUM_TOKENS=16 -v atlasmart-cass-1-data:/var/lib/cassandra cassandra:5.0.9# Wait until node 1 accepts CQL before starting peers.docker run -d --name atlasmart-cass-2 --hostname atlasmart-cass-2 --network atlasmart-cassandra -e CASSANDRA_CLUSTER_NAME=atlasmart-course -e CASSANDRA_SEEDS=atlasmart-cass-1 -e CASSANDRA_DC=dc1 -e CASSANDRA_RACK=rack2 -e CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch -e CASSANDRA_NUM_TOKENS=16 -v atlasmart-cass-2-data:/var/lib/cassandra cassandra:5.0.9docker run -d --name atlasmart-cass-3 --hostname atlasmart-cass-3 --network atlasmart-cassandra -e CASSANDRA_CLUSTER_NAME=atlasmart-course -e CASSANDRA_SEEDS=atlasmart-cass-1 -e CASSANDRA_DC=dc1 -e CASSANDRA_RACK=rack3 -e CASSANDRA_ENDPOINT_SNITCH=GossipingPropertyFileSnitch -e CASSANDRA_NUM_TOKENS=16 -v atlasmart-cass-3-data:/var/lib/cassandra cassandra:5.0.9# Wait for all nodes to become Up/Normal.docker exec atlasmart-cass-1 nodetool statusdocker exec atlasmart-cass-1 nodetool version

Query the server metadata and configuration rather than assuming the course baseline:

evidence · partitioner, local tokens, vnode count
docker exec atlasmart-cass-1 cqlsh -e "SELECT cluster_name, partitioner, tokens FROM system.local;"docker exec atlasmart-cass-1 sh -lc "grep -E '^(partitioner:|num_tokens:|allocate_tokens_for_local_replication_factor:)' /etc/cassandra/cassandra.yaml"docker exec atlasmart-cass-1 nodetool status

Expected invariants: system.local.partitioner names Murmur3Partitioner; the course container configuration shows 16 tokens; system.local.tokens contains multiple token strings for node 1; and nodetool status reports each physical node once while its Tokens column reflects the vnode count. Exact token values are intentionally not prescribed.

The tokens collection is local control-plane metadata. It says which ring positions this node owns; it does not by itself say which keyspace replicas contain a partition, because replication strategy and rack/DC placement are additional inputs.

3. Map AtlasMart partition keys to tokens with CQL

AtlasMart fixture · RF=3 products_by_id
docker exec atlasmart-cass-1 cqlsh -e "CREATE KEYSPACE IF NOT EXISTS atlasmart_tokens WITH replication = {'class':'NetworkTopologyStrategy','dc1':3};"docker exec atlasmart-cass-1 cqlsh -e "CREATE TABLE IF NOT EXISTS atlasmart_tokens.products_by_id (product_id text PRIMARY KEY, category text, name text, price_cents int);"docker exec atlasmart-cass-1 cqlsh -e "INSERT INTO atlasmart_tokens.products_by_id (product_id,category,name,price_cents) VALUES ('p-1001','laptop','AtlasBook 14',129900); INSERT INTO atlasmart_tokens.products_by_id (product_id,category,name,price_cents) VALUES ('p-1002','camera','AtlasCam X',89900); INSERT INTO atlasmart_tokens.products_by_id (product_id,category,name,price_cents) VALUES ('p-1003','audio','AtlasPods',14900); INSERT INTO atlasmart_tokens.products_by_id (product_id,category,name,price_cents) VALUES ('p-2001','home','AtlasLamp',7900);"

CQL exposes the partitioner's mapping through token(). Because functions are valid selectors, the lab can display both the business key and the computed token:

CQL · deterministic key → token mapping
docker exec atlasmart-cass-1 cqlsh -e "SELECT product_id, token(product_id) AS token_value, category FROM atlasmart_tokens.products_by_id;"# Compute the same token directly from a literal in a table-aware SELECT.docker exec atlasmart-cass-1 cqlsh -e "SELECT token(product_id) AS token_value FROM atlasmart_tokens.products_by_id WHERE product_id='p-1001';"

Record the token for each product. Re-run the SELECT from node 2. The token for p-1001 must not change just because another coordinator executed the query. That repeatability is the important evidence; whether its token is positive or negative is not.

Observation What it proves What it does not prove
Same key → same token Deterministic partitioner mapping Which coordinator the driver will choose
Different keys → apparently scattered tokens Hash-based distribution intent Perfect balance for a tiny sample
One token value Ring position for that partition key All physical replicas without keyspace replication metadata

4. From token to replicas: partitioner plus replication strategy

For a write, the coordinator computes the token and consults token metadata plus the keyspace's replication strategy. Under NetworkTopologyStrategy with dc1:3, the natural replica set contains three distinct physical nodes while respecting rack placement where possible. The coordinator may itself be a replica, but that is not required.

cqlsh in current Cassandra can expose the replica set for a token with SHOW REPLICAS. Copy one token value from the previous query and substitute it below:

cqlsh · token → natural replicas
# Replace TOKEN_VALUE with the bigint captured for p-1001.docker exec -it atlasmart-cass-1 cqlsh# In cqlsh:SHOW REPLICAS TOKEN_VALUE atlasmart_tokens;

If all three course nodes are replicas because RF=3 on a three-node DC, do not infer that every production keyspace behaves that way. Later Chapter 04 changes RF explicitly and derives placement math. The conceptual pipeline remains: partition-key bytes → partitioner → token → token range → replication strategy → natural replicas.

5. Wrong model: “monotonic IDs will distribute round-robin”

A practitioner familiar with sharded integer ranges might expect 1001, 1002, 1003 to move through nodes in order. Murmur3 does not assign partitions round-robin and does not preserve the original key's lexical ordering. That is usually beneficial because regular business keys are spread over the token space without requiring the application to know the node count.

The more dangerous mistake is the opposite: believing the hash function fixes a key with too few distinct values. A table partitioned only by region with values north, south, east, and west has four partitions regardless of cluster size. Under heavy traffic those four token positions can dominate four replica sets. The repair is a query-first partition-key design with sufficient cardinality and bounded partitions—not a custom partitioner or more nodes.

Verification checklist

  • You captured the active partitioner and vnode count from the running lab.
  • You mapped at least four deterministic partition keys to tokens.
  • The same key produced the same token through different coordinators.
  • You resolved at least one token to its natural replicas.
  • You can explain why low partition-key cardinality survives hashing as a hotspot risk.

Check your understanding

  1. What exact input does the partitioner receive conceptually?
  2. Does p-1002 have to hash next to p-1001?
  3. Does the token alone define all replicas?
  4. Can adding nodes fix one constant partition key?
  5. Why verify the running partitioner instead of assuming Murmur3?
Review the answers

1. The serialized partition-key value or composite partition-key components, not clustering columns or the full row.

2. No. Murmur3 is distribution-oriented and does not preserve lexical adjacency.

3. No. Token ownership plus the keyspace replication strategy and topology determine natural replicas.

4. No. One partition key still hashes to one token; its request concentration remains on that partition replica set.

5. Partitioner choice is cluster metadata/configuration and is version/deployment-sensitive; correctness depends on the actual cluster.

Cleanup

cleanup · Bash; remove only course-owned resources
docker rm -f atlasmart-cass-4 atlasmart-cass-1 atlasmart-cass-2 atlasmart-cass-3 2>/dev/null || truedocker volume rm atlasmart-cass-4-data atlasmart-cass-1-data atlasmart-cass-2-data atlasmart-cass-3-data 2>/dev/null || truedocker network rm atlasmart-cassandra 2>/dev/null || true
cleanup · PowerShell; remove only course-owned resources
docker rm -f atlasmart-cass-4 atlasmart-cass-1 atlasmart-cass-2 atlasmart-cass-3 2>$nulldocker volume rm atlasmart-cass-4-data atlasmart-cass-1-data atlasmart-cass-2-data atlasmart-cass-3-data 2>$nulldocker network rm atlasmart-cassandra 2>$null

Summary and next step

This lesson’s concepts, evidence path, failure boundaries, and production judgment should now be explicit enough to verify rather than assume. Re-run the check-your-understanding prompts and preserve any lab evidence you need before changing or cleaning up the environment.

Next, continue to Token Ranges, Ownership, Replicas, and Why the Ring Is a Useful Mental Model.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.