Skip to content

Commit 926fd27

Browse files
authored
Merge pull request #1126 from fatkodima/redis_distributed-change-hashing
Use `MD5` for hashing server nodes in `Redis::Distributed`
2 parents 6455441 + d398d09 commit 926fd27

File tree

3 files changed

+17
-5
lines changed

3 files changed

+17
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
# Unreleased 5.0.0
44

5+
- Use `MD5` for hashing server nodes in `Redis::Distributed`. This should improve keys distribution among servers. See #1089.
56
- Cluster support has been moved to a `redis_cluster` companion gem.
67
- `select` no longer record the current database. If the client has to reconnect after `select` was used, it will reconnect to the original database.
78
- Removed `logger` option.

lib/redis/hash_ring.rb

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# frozen_string_literal: true
22

33
require 'zlib'
4+
require 'digest/md5'
45

56
class Redis
67
class HashRing
@@ -25,7 +26,7 @@ def initialize(nodes = [], replicas = POINTS_PER_SERVER)
2526
def add_node(node)
2627
@nodes << node
2728
@replicas.times do |i|
28-
key = Zlib.crc32("#{node.id}:#{i}")
29+
key = server_hash_for("#{node.id}:#{i}")
2930
@ring[key] = node
3031
@sorted_keys << key
3132
end
@@ -35,7 +36,7 @@ def add_node(node)
3536
def remove_node(node)
3637
@nodes.reject! { |n| n.id == node.id }
3738
@replicas.times do |i|
38-
key = Zlib.crc32("#{node.id}:#{i}")
39+
key = server_hash_for("#{node.id}:#{i}")
3940
@ring.delete(key)
4041
@sorted_keys.reject! { |k| k == key }
4142
end
@@ -49,8 +50,8 @@ def get_node(key)
4950
def get_node_pos(key)
5051
return [nil, nil] if @ring.empty?
5152

52-
crc = Zlib.crc32(key)
53-
idx = HashRing.binary_search(@sorted_keys, crc)
53+
hash = hash_for(key)
54+
idx = HashRing.binary_search(@sorted_keys, hash)
5455
[@ring[@sorted_keys[idx]], idx]
5556
end
5657

@@ -85,5 +86,15 @@ def self.binary_search(ary, value)
8586
upper = ary.size - 1 if upper < 0
8687
upper
8788
end
89+
90+
private
91+
92+
def hash_for(key)
93+
Zlib.crc32(key)
94+
end
95+
96+
def server_hash_for(key)
97+
Digest::MD5.digest(key).unpack1("L>")
98+
end
8899
end
89100
end

test/distributed/key_tags_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ def test_allows_clustering_of_keys
2828
end
2929

3030
def test_distributes_keys_if_no_clustering_is_used
31-
r.add_node("redis://127.0.0.1:#{PORT}/14")
31+
r.add_node("redis://127.0.0.1:#{PORT}/13")
3232
r.flushdb
3333

3434
r.set "users:1", 1

0 commit comments

Comments
 (0)