Skip to main content

Simulating a consistent hashing node ring


Why simulate consistent hashing? #

Understanding distributed systems concepts often requires more than just reading about them. Consistent hashing is fundamental to how distributed systems like databases, caches, and load balancers manage data across multiple nodes, but the mechanics can be abstract.

Rather than just explaining the theory, building an interactive simulator helps visualize exactly how keys get distributed, what happens when nodes join or leave, and how the system maintains balance.

If you need a refresher on consistent hashing fundamentals, check out my previous post on consistent hashing which covers the core concepts and mathematics.

What we want to simulate #

The simulator models the essential operations of a consistent hashing system:

  • Node management: Adding nodes to the ring and removing them to simulate scaling up or handling failures. Each node gets positioned on the hash ring based on its hash value.

  • Key operations: Inserting keys that need to be stored somewhere in the system and removing keys that are no longer needed. Each key gets assigned to the next clockwise node on the ring.

  • Dynamic redistribution: When nodes are added or removed, only the keys that need to move actually get redistributed. This is the key advantage of consistent hashing, where there’s minimal data movement during topology changes.

The simulator persists all operations so you can experiment with different scenarios and observe how the system behaves under various conditions.

Building the simulator components #

The simulator consists of three main components working together:

Hash ring implementation #

The core consistent hashing logic uses SHA-256 to generate hash positions for both nodes and keys. The hash ring maintains a sorted structure of node positions, making it efficient to find the successor node for any given key.

Each node gets positioned on a ring with a maximum hash value of 2^32 - 1. When a key needs to be assigned, we find the first node clockwise from the key’s hash position. If no node exists clockwise, we wrap around to the beginning of the ring.

Interactive web interface #

The frontend provides controls for adding and removing nodes by name, as well as inserting and deleting keys. All operations update the visualization in real-time, making it easy to see the immediate effects of changes.

The interface includes data tables showing the current state of nodes and keys, along with statistics about the hash ring distribution. This helps understand how well-balanced the system is at any given time.

Persistent storage #

All operations get stored in a SQLite database, maintaining a complete history of the system state. The database tracks nodes with their hash positions and keys with their assigned nodes, enabling the simulator to handle complex scenarios reliably.

Hashing and node assignment #

The simulator uses a straightforward but effective hashing approach:

Hash function #

hashFunction(input) {
  const hash = crypto.createHash('sha256')
    .update(input)
    .digest('hex')
    .substring(0, 8);
  return parseInt(hash, 16);
}

This creates a 32-bit hash space from the SHA-256 output, providing good distribution properties while keeping the visualization manageable.

Node assignment algorithm #

For any key, the assignment process finds the successor node by scanning clockwise around the ring:

findSuccessorNode(keyHash) {
  const sortedPositions = Array.from(this.hashRing.keys()).sort((a, b) => a - b);

  for (const position of sortedPositions) {
    if (position >= keyHash) {
      return this.hashRing.get(position);
    }
  }

  return this.hashRing.get(sortedPositions[0]);
}

This guarantees that keys are consistently assigned to the same node as long as the ring topology doesn’t change, and minimizes reassignment when it does.

Running the simulator #

The simulator runs as a local web application that you can experiment with immediately.

Quick start #

git clone https://github.com/pdulapalli/consistent-hashing-node-simulator
cd consistent-hashing-node-simulator
npm install
npm run dev

Open your browser to http://localhost:3000 and start experimenting.

Some scenarios you can try #

  • Add several nodes and then insert many keys. Watch how they distribute across the ring and calculate the distribution percentages.

  • Remove a node and observe which keys get reassigned. Notice that only the keys originally assigned to that node need to move.

  • Add a new node to an existing ring with keys. See how the new node takes responsibility for a portion of the key space, relieving load from its neighbors.

  • Try adding nodes with similar names (which may hash to nearby positions) and observe how this affects distribution balance.

The visualization updates in real-time as you make changes, providing immediate feedback on how your operations affect the system’s behavior.

Demo #

Try out the demo here!

Code #

The complete implementation is available on GitHub here.