consistent_hashr 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 1.0.0
1
+ 1.1.0
@@ -1,26 +1,18 @@
1
1
  require 'zlib'
2
+ module ConsistentHashr
2
3
 
3
- class ConsistentHashr
4
-
5
- ##
6
- # Creates a new Hasher. Servers should be a hash.
7
- def initialize(_servers = {}, _number_of_replicas = 50)
8
- @circle = {}
9
- @number_of_replicas = _number_of_replicas
10
- _servers.each do |name, server|
11
- add_server(name, server)
12
- end
13
- end
4
+ @circle = {}
5
+ @number_of_replicas = 20
14
6
 
15
7
  ##
16
8
  # Computes a key
17
- def hash_key(key)
9
+ def self.hash_key(key)
18
10
  Zlib.crc32("#{key}")
19
11
  end
20
12
 
21
13
  ##
22
14
  # Adds a server to the circle
23
- def add_server(_name, _server)
15
+ def self.add_server(_name, _server)
24
16
  @number_of_replicas.times do |t|
25
17
  @circle[hash_key("#{_name}+#{t}")] = _server
26
18
  end
@@ -28,7 +20,7 @@ class ConsistentHashr
28
20
 
29
21
  ##
30
22
  # Returns the server for the provided key
31
- def get(key)
23
+ def self.get(key)
32
24
  return nil if @circle.empty?
33
25
  return @circle.first.last if @circle.size == 1
34
26
 
@@ -3,7 +3,9 @@ require File.dirname(__FILE__) + "/spec_helper"
3
3
  describe ConsistentHashr do
4
4
  before(:each) do
5
5
  @servers = {:s1 => "s1", :s2 => "s2", :s3 => "s3", :s4 => "s4", :s5 => "s5", :s6 => "s6"}
6
- @hashr = ConsistentHashr.new(@servers)
6
+ @servers.each do |n, s|
7
+ ConsistentHashr.add_server(n,s)
8
+ end
7
9
  end
8
10
 
9
11
  it "should not change more than 75% of keys" do
@@ -11,14 +13,34 @@ describe ConsistentHashr do
11
13
  1000.times do |idx|
12
14
  keys << rand(100000).to_s
13
15
  end
14
- before = keys.map() { |k| @hashr.get(k)}
16
+ before = keys.map() { |k| ConsistentHashr.get(k)}
15
17
 
16
- @hashr.add_server(:s7, "s7")
18
+ ConsistentHashr.add_server(:s7, "s7")
17
19
 
18
- after = keys.map() { |k| @hashr.get(k)}
20
+ after = keys.map() { |k| ConsistentHashr.get(k)}
19
21
 
20
22
  diff = before.zip(after).find_all {|a| a[0] == a[1] }.size
21
23
  diff.should > keys.size*0.7
22
24
  end
23
25
 
26
+ it "should distribute keys evenly accross servers" do
27
+ keys = []
28
+ 10000.times do |idx|
29
+ keys << rand(100000).to_s
30
+ end
31
+ servers = keys.map() { |k| ConsistentHashr.get(k)}
32
+
33
+ count_by_server = {}
34
+ servers.each do |s|
35
+ count_by_server[s] ||= 0
36
+ count_by_server[s] += 1
37
+ end
38
+
39
+ min = count_by_server.invert.sort.first.first
40
+ max = count_by_server.invert.sort.last.first
41
+
42
+ max.should < min * 2
43
+
44
+ end
45
+
24
46
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
+ - 1
7
8
  - 0
8
- - 0
9
- version: 1.0.0
9
+ version: 1.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - julien