redis_failover 0.5.3 → 0.5.4
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/Changes.md +4 -0
- data/lib/redis_failover/client.rb +27 -28
- data/lib/redis_failover/node.rb +1 -1
- data/lib/redis_failover/node_manager.rb +13 -12
- data/lib/redis_failover/version.rb +1 -1
- data/lib/redis_failover/zk_client.rb +20 -32
- metadata +15 -15
data/Changes.md
CHANGED
@@ -109,37 +109,37 @@ module RedisFailover
|
|
109
109
|
private
|
110
110
|
|
111
111
|
def setup_zookeeper_client
|
112
|
-
@zkclient = ZkClient.new(@zkservers)
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
purge_clients
|
118
|
-
end
|
112
|
+
@zkclient = ZkClient.new(@zkservers) do |client|
|
113
|
+
# when session expires, purge client list
|
114
|
+
client.on_session_expiration do
|
115
|
+
purge_clients
|
116
|
+
end
|
119
117
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
118
|
+
# when we are disconnected, purge client list
|
119
|
+
client.event_handler.register_state_handler(:connecting) do
|
120
|
+
purge_clients
|
121
|
+
end
|
124
122
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
123
|
+
# when session is recovered, watch again
|
124
|
+
client.on_session_recovered do
|
125
|
+
client.stat(@znode, :watch => true)
|
126
|
+
end
|
129
127
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
128
|
+
# register a watcher for future changes
|
129
|
+
client.watcher.register(@znode) do |event|
|
130
|
+
if event.node_created? || event.node_changed?
|
131
|
+
update_znode_timestamp
|
132
|
+
build_clients
|
133
|
+
elsif event.node_deleted?
|
134
|
+
update_znode_timestamp
|
135
|
+
purge_clients
|
136
|
+
client.stat(@znode, :watch => true)
|
137
|
+
else
|
138
|
+
logger.error("Unknown ZK node event: #{event.inspect}")
|
139
|
+
end
|
141
140
|
end
|
142
141
|
end
|
142
|
+
update_znode_timestamp
|
143
143
|
end
|
144
144
|
|
145
145
|
def redis_operation?(method)
|
@@ -177,8 +177,7 @@ module RedisFailover
|
|
177
177
|
end
|
178
178
|
|
179
179
|
def master
|
180
|
-
master = @lock.synchronize { @master }
|
181
|
-
if master
|
180
|
+
if master = @lock.synchronize { @master }
|
182
181
|
verify_role!(master, :master)
|
183
182
|
return master
|
184
183
|
end
|
data/lib/redis_failover/node.rb
CHANGED
@@ -52,7 +52,7 @@ module RedisFailover
|
|
52
52
|
perform_operation do |redis|
|
53
53
|
unless slave_of?(master)
|
54
54
|
redis.slaveof(master.host, master.port)
|
55
|
-
logger.info("#{self} now a slave of master #{master}")
|
55
|
+
logger.info("#{self} is now a slave of master #{master}")
|
56
56
|
wakeup
|
57
57
|
end
|
58
58
|
end
|
@@ -86,9 +86,9 @@ module RedisFailover
|
|
86
86
|
def handle_syncing(node)
|
87
87
|
reconcile(node)
|
88
88
|
|
89
|
-
if node.prohibits_stale_reads?
|
89
|
+
if node.syncing_with_master? && node.prohibits_stale_reads?
|
90
90
|
logger.info("Node #{node} not ready yet, still syncing with master.")
|
91
|
-
|
91
|
+
force_unavailable_slave(node)
|
92
92
|
return
|
93
93
|
end
|
94
94
|
|
@@ -119,45 +119,46 @@ module RedisFailover
|
|
119
119
|
nodes = @options[:nodes].map { |opts| Node.new(opts) }.uniq
|
120
120
|
raise NoMasterError unless @master = find_master(nodes)
|
121
121
|
@slaves = nodes - [@master]
|
122
|
+
logger.info("Managing master (#{@master}) and slaves" +
|
123
|
+
" (#{@slaves.map(&:to_s).join(', ')})")
|
122
124
|
|
123
125
|
# ensure that slaves are correctly pointing to this master
|
124
126
|
redirect_slaves_to_master
|
125
|
-
|
126
|
-
logger.info("Managing master (#{@master}) and slaves" +
|
127
|
-
" (#{@slaves.map(&:to_s).join(', ')})")
|
128
127
|
end
|
129
128
|
|
130
129
|
def spawn_watchers
|
131
|
-
@watchers = [@master,
|
130
|
+
@watchers = [@master, @slaves, @unavailable].flatten.map do |node|
|
132
131
|
NodeWatcher.new(self, node, @options[:max_failures] || 3)
|
133
132
|
end
|
134
133
|
@watchers.each(&:watch)
|
135
134
|
end
|
136
135
|
|
137
136
|
def find_master(nodes)
|
138
|
-
# try to find the master - if the actual master is currently
|
139
|
-
# down, it will be handled by its watcher
|
140
137
|
nodes.find do |node|
|
141
138
|
begin
|
142
139
|
node.master?
|
143
140
|
rescue NodeUnavailableError
|
144
|
-
# will eventually be handled by watcher
|
145
141
|
false
|
146
142
|
end
|
147
143
|
end
|
148
144
|
end
|
149
145
|
|
150
146
|
def redirect_slaves_to_master
|
151
|
-
|
152
|
-
@slaves.each do |slave|
|
147
|
+
@slaves.dup.each do |slave|
|
153
148
|
begin
|
154
149
|
slave.make_slave!(@master)
|
155
150
|
rescue NodeUnavailableError
|
156
|
-
|
151
|
+
logger.info("Failed to redirect unreachable slave #{slave} to master #{@master}")
|
152
|
+
force_unavailable_slave(slave)
|
157
153
|
end
|
158
154
|
end
|
159
155
|
end
|
160
156
|
|
157
|
+
def force_unavailable_slave(node)
|
158
|
+
@slaves.delete(node)
|
159
|
+
@unavailable << node unless @unavailable.include?(node)
|
160
|
+
end
|
161
|
+
|
161
162
|
# It's possible that a newly available node may have been restarted
|
162
163
|
# and completely lost its dynamically set run-time role by the node
|
163
164
|
# manager. This method ensures that the node resumes its role as
|
@@ -15,9 +15,18 @@ module RedisFailover
|
|
15
15
|
ZookeeperExceptions::ZookeeperException::ConnectionClosed,
|
16
16
|
ZookeeperExceptions::ZookeeperException::NotConnected
|
17
17
|
].freeze
|
18
|
+
WRAPPED_ZK_METHODS = [
|
19
|
+
:get,
|
20
|
+
:set,
|
21
|
+
:watcher,
|
22
|
+
:event_handler,
|
23
|
+
:stat,
|
24
|
+
:create,
|
25
|
+
:delete].freeze
|
18
26
|
|
19
|
-
def initialize(servers)
|
27
|
+
def initialize(servers, &setup_block)
|
20
28
|
@servers = servers
|
29
|
+
@setup_block = setup_block
|
21
30
|
@lock = Mutex.new
|
22
31
|
build_client
|
23
32
|
end
|
@@ -32,32 +41,14 @@ module RedisFailover
|
|
32
41
|
@on_session_recovered = block
|
33
42
|
end
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def watcher(*args, &block)
|
44
|
-
perform_with_reconnect { @client.watcher(*args, &block) }
|
45
|
-
end
|
46
|
-
|
47
|
-
def event_handler(*args, &block)
|
48
|
-
perform_with_reconnect { @client.event_handler(*args, &block) }
|
49
|
-
end
|
50
|
-
|
51
|
-
def stat(*args, &block)
|
52
|
-
perform_with_reconnect { @client.stat(*args, &block) }
|
53
|
-
end
|
54
|
-
|
55
|
-
def create(*args, &block)
|
56
|
-
perform_with_reconnect { @client.create(*args, &block) }
|
57
|
-
end
|
58
|
-
|
59
|
-
def delete(*args, &block)
|
60
|
-
perform_with_reconnect { @client.delete(*args, &block) }
|
44
|
+
WRAPPED_ZK_METHODS.each do |zk_method|
|
45
|
+
class_eval <<-RUBY
|
46
|
+
def #{zk_method}(*args, &block)
|
47
|
+
perform_with_reconnect do
|
48
|
+
@client.#{zk_method}(*args, &block)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
RUBY
|
61
52
|
end
|
62
53
|
|
63
54
|
private
|
@@ -83,11 +74,8 @@ module RedisFailover
|
|
83
74
|
|
84
75
|
def build_client
|
85
76
|
@lock.synchronize do
|
86
|
-
|
87
|
-
|
88
|
-
else
|
89
|
-
@client = ZK.new(@servers)
|
90
|
-
end
|
77
|
+
@client = ZK.new(@servers)
|
78
|
+
@setup_block.call(self) if @setup_block
|
91
79
|
logger.info("Communicating with ZooKeeper servers #{@servers}")
|
92
80
|
end
|
93
81
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis_failover
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-04-18 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: redis
|
16
|
-
requirement: &
|
16
|
+
requirement: &70362366935580 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70362366935580
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: redis-namespace
|
27
|
-
requirement: &
|
27
|
+
requirement: &70362366935160 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70362366935160
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: multi_json
|
38
|
-
requirement: &
|
38
|
+
requirement: &70362366934740 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70362366934740
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: zk
|
49
|
-
requirement: &
|
49
|
+
requirement: &70362366934320 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70362366934320
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rake
|
60
|
-
requirement: &
|
60
|
+
requirement: &70362366933900 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70362366933900
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
|
-
requirement: &
|
71
|
+
requirement: &70362366933480 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,7 +76,7 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70362366933480
|
80
80
|
description: Redis Failover is a ZooKeeper-based automatic master/slave failover solution
|
81
81
|
for Ruby
|
82
82
|
email:
|
@@ -129,7 +129,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
129
129
|
version: '0'
|
130
130
|
segments:
|
131
131
|
- 0
|
132
|
-
hash:
|
132
|
+
hash: 610999762978001666
|
133
133
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
134
|
none: false
|
135
135
|
requirements:
|
@@ -138,7 +138,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
138
|
version: '0'
|
139
139
|
segments:
|
140
140
|
- 0
|
141
|
-
hash:
|
141
|
+
hash: 610999762978001666
|
142
142
|
requirements: []
|
143
143
|
rubyforge_project:
|
144
144
|
rubygems_version: 1.8.16
|