consistent_hashr 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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