]>
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 @replicas.times
do |i
|
35 key
= Zlib
.crc32("#{node}:#{count}")
37 @sorted_keys.reject!
{|k
| k
== key
}
41 # get the node in the hash ring for this key
47 return [nil,nil] if @ring.size
== 0
49 idx
= HashRing
.binary_search(@sorted_keys, crc
)
50 return [@ring[@sorted_keys[idx
]], idx
]
54 return [nil,nil] if @ring.size
== 0
55 node
, pos
= get_node_pos(key
)
56 @sorted_keys[pos
..-1].each
do |k
|
63 # gem install RubyInline to use this code
64 # Native extension to perform the binary search within the hashring.
65 # There's a pure ruby version below so this is purely optional
66 # for performance. In testing 20k gets and sets, the native
67 # binary search shaved about 12% off the runtime (9sec -> 8sec).
72 int binary_search(VALUE ary, unsigned int r) {
73 int upper = RARRAY_LEN(ary) - 1;
77 while (lower <= upper) {
78 idx = (lower + upper) / 2;
80 VALUE continuumValue = RARRAY_PTR(ary)[idx];
81 unsigned int l = NUM2UINT(continuumValue);
97 # Find the closest index in HashRing with value <= the given value
98 def binary_search(ary
, value
, &block
)
103 while(lower
<= upper
) do
104 idx
= (lower + upper
) / 2
105 comp
= ary
[idx
] <=> value
123 # ring = HashRing.new ['server1', 'server2', 'server3']
126 # p ring.get_node "kjhjkjlkjlkkh"