]>
git.saurik.com Git - redis.git/blob - client-libraries/ruby/lib/hash_ring.rb
5 POINTS_PER_SERVER
= 160 # this is the default in libmemcached
7 attr_reader
:ring, :sorted_keys, :replicas, :nodes
9 # nodes is a list of objects that have a proper to_s representation.
10 # replicas indicates how many virtual points should be used pr. node,
11 # replicas are required to improve the distribution.
12 def initialize(nodes
=[], replicas
=POINTS_PER_SERVER
)
22 # Adds a `node` to the hash ring (including a number of replicas).
25 @replicas.times
do |i
|
26 key
= Zlib
.crc32("#{node}:#{i}")
34 @nodes.reject!
{|n
| n
.to_s
== node
.to_s
}
35 @replicas.times
do |i
|
36 key
= Zlib
.crc32("#{node}:#{i}")
38 @sorted_keys.reject!
{|k
| k
== key
}
42 # get the node in the hash ring for this key
48 return [nil,nil] if @ring.size
== 0
50 idx
= HashRing
.binary_search(@sorted_keys, crc
)
51 return [@ring[@sorted_keys[idx
]], idx
]
55 return [nil,nil] if @ring.size
== 0
56 node
, pos
= get_node_pos(key
)
57 @sorted_keys[pos
..-1].each
do |k
|
64 # gem install RubyInline to use this code
65 # Native extension to perform the binary search within the hashring.
66 # There's a pure ruby version below so this is purely optional
67 # for performance. In testing 20k gets and sets, the native
68 # binary search shaved about 12% off the runtime (9sec -> 8sec).
73 int binary_search(VALUE ary, unsigned int r) {
74 int upper = RARRAY_LEN(ary) - 1;
78 while (lower <= upper) {
79 idx = (lower + upper) / 2;
81 VALUE continuumValue = RARRAY_PTR(ary)[idx];
82 unsigned int l = NUM2UINT(continuumValue);
98 # Find the closest index in HashRing with value <= the given value
99 def binary_search(ary
, value
, &block
)
104 while(lower
<= upper
) do
105 idx
= (lower + upper
) / 2
106 comp
= ary
[idx
] <=> value
124 # ring = HashRing.new ['server1', 'server2', 'server3']
127 # p ring.get_node "kjhjkjlkjlkkh"