Class: RedisRing::Master

Inherits:
Object
  • Object
show all
Defined in:
lib/redis_ring/master.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(zookeeper_connection, ring_size, node_provider) ⇒ Master

Returns a new instance of Master.



7
8
9
10
11
12
13
# File 'lib/redis_ring/master.rb', line 7

def initialize(zookeeper_connection, ring_size, node_provider)
  @zookeeper_connection = zookeeper_connection
  @ring_size = ring_size
  @node_provider = node_provider
  @node_ids = []
  @is_master = false
end

Instance Attribute Details

#node_providerObject (readonly)

Returns the value of attribute node_provider.



5
6
7
# File 'lib/redis_ring/master.rb', line 5

def node_provider
  @node_provider
end

#ring_sizeObject (readonly)

Returns the value of attribute ring_size.



5
6
7
# File 'lib/redis_ring/master.rb', line 5

def ring_size
  @ring_size
end

#zookeeper_connectionObject (readonly)

Returns the value of attribute zookeeper_connection.



5
6
7
# File 'lib/redis_ring/master.rb', line 5

def zookeeper_connection
  @zookeeper_connection
end

Instance Method Details

#became_masterObject



15
16
17
18
19
20
21
# File 'lib/redis_ring/master.rb', line 15

def became_master
  return if is_master?

  puts "BECAME MASTER"

  @is_master = true
end

#is_master?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/redis_ring/master.rb', line 59

def is_master?
  return @is_master
end

#no_longer_is_masterObject



23
24
25
26
27
28
29
# File 'lib/redis_ring/master.rb', line 23

def no_longer_is_master
  return unless is_master?

  puts "LOST MASTER STATUS"

  @is_master = false
end

#node_joined(node_id) ⇒ Object



46
47
48
49
50
# File 'lib/redis_ring/master.rb', line 46

def node_joined(node_id)
  puts "NODE JOINED #{node_id}"

  reassign_shards
end

#node_leaving(node_id) ⇒ Object



52
53
54
55
56
57
# File 'lib/redis_ring/master.rb', line 52

def node_leaving(node_id)
  puts "NODE LEAVING #{node_id}"

  node_ids.delete(node_id)
  reassign_shards
end

#nodes_changed(changed_node_ids) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/redis_ring/master.rb', line 31

def nodes_changed(changed_node_ids)
  return unless is_master?

  new_nodes = changed_node_ids - node_ids
  removed_nodes = node_ids - changed_node_ids

  puts "NODES CHANGED"
  puts "NEW: #{new_nodes.join(", ")}" if new_nodes.any?
  puts "REMOVED: #{removed_nodes.join(', ')}" if removed_nodes.any?

  @node_ids = changed_node_ids

  reassign_shards
end

#reassign_shardsObject



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/redis_ring/master.rb', line 63

def reassign_shards
  update_node_statuses

  running_shards = {}
  best_candidates = {}
  best_candidates_timestamps = Hash.new(0)

  nodes.each do |node_id, node|
    node.running_shards.dup.each do |shard_no|
      if running_shards.key?(shard_no)
        node.stop_shard(shard_no)
      else
        running_shards[shard_no] = node_id
      end
    end

    node.available_shards.each do |shard_no, timestamp|
      if timestamp > best_candidates_timestamps[shard_no]
        best_candidates[shard_no] = node_id
        best_candidates_timestamps[shard_no] = timestamp
      end
    end
  end

  offline_shards = (0...ring_size).to_a - running_shards.keys
  shards_per_node = (1.0 * ring_size / nodes.size).floor
  rest = ring_size - shards_per_node * nodes.size

  nodes.each do |node_id, node|
    next unless node.joined?
    break if offline_shards.empty?
    count_to_assign = shards_per_node - node.running_shards.size
    count_to_assign += 1 if node_ids.index(node_id) < rest
    count_to_assign.times do
      shard_no = offline_shards.shift
      break unless shard_no
      node.start_shard(shard_no)
    end
  end

  zookeeper_connection.update_status(status)
end

#statusObject



106
107
108
109
110
111
# File 'lib/redis_ring/master.rb', line 106

def status
  {
    :ring_size => ring_size,
    :shards => shards
  }
end