uhashring Consistent Hashing Library
uhashring is a full-featured pure Python library for consistent hashing, primarily used in distributed systems, caches, and databases to efficiently distribute data across nodes. It aims to prevent total reshuffling of key-node mappings when nodes are added or removed. The library offers Ketama compatibility, customizable hash and weight functions, and supports instance-oriented usage. The current version is 2.4, with releases occurring periodically, as evidenced by its PyPI update in April 2025 and ongoing GitHub activity. [1, 2]
Warnings
- breaking Since v1.0, the default hash function changed from 'ketama' to 'md5', and the default number of vnodes per node increased from 40 to 160. This change was made for linear performance on node changes but breaks compatibility with older setups relying on the Ketama default. [1]
- deprecated Python 2 support was dropped. `uhashring` versions 1.2 and newer do not support Python 2. [1]
- gotcha When using `hash_fn='ketama'`, adding or removing nodes requires a complete ring regeneration, which can degrade performance in rapidly changing environments. The default MD5 implementation provides linear performance for these operations. [1]
- gotcha Custom node weights significantly influence key distribution. Incorrectly configured weights can lead to uneven load distribution or 'hotspots' on specific nodes. [1]
Install
-
pip install uhashring
Imports
- HashRing
from uhashring import HashRing
Quickstart
from uhashring import HashRing
# Initialize a consistent hash ring with nodes
hr = HashRing(nodes=['node1', 'node2', 'node3'])
# Get the node responsible for a given key
key_to_find = "my_data_key"
responsible_node = hr.get_node(key_to_find)
print(f"Key '{key_to_find}' maps to node: {responsible_node}")
# Add a new node with a custom weight
hr.add_node('node4', {'weight': 10})
# Remove a node
hr.remove_node('node2')
# Get the distribution of keys across nodes (after changes)
# Note: This is an example, actual distribution varies with keys and hash function.
# For a real application, you'd query 'get_node' for many keys to see the effect.
print("Current node configuration:", hr.conf)
print("Node distribution (example property, not a real-time key distribution):")
# The 'distribution' property is a Counter of how many points each node occupies on the ring.
print(hr.distribution)