redis-sentinel 1.4.4 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +8 -0
- data/README.md +5 -0
- data/Rakefile +1 -1
- data/example/redis-master.conf +1 -1
- data/example/redis-slave.conf +1 -1
- data/lib/redis-sentinel/client.rb +37 -5
- data/lib/redis-sentinel/version.rb +1 -1
- data/spec/redis-sentinel/client_spec.rb +1 -1
- data/spec/redis-sentinel/em_client_spec.rb +2 -1
- metadata +18 -20
- data/.ruby-gemset +0 -1
- data/.ruby-version +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 822e055ecb4e148a1bf08b701e21f6712c519373
|
4
|
+
data.tar.gz: de6b225b065c14d3e429f19a94aa786aa728c9f2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b6a20ab1e214763b79a47aa0122ea054e45ee9527512a1a56ffc27f6caea384c495d153fe229cb184459e8482805eef7d3377387a83ed377c0d0710952ecda2
|
7
|
+
data.tar.gz: 00e40455360c4969dca6f38cfe2aa9707ead89f04e4a0eff35565ac3977c471979acc23f22ff18524337867d942734ab37dc3c0a44a3fff3b3012c017f8350f7
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
+
## 1.5.0
|
4
|
+
|
5
|
+
* Subscribe +switch-master again
|
6
|
+
* Prevents master discovery to get stuck in endless loop if sentinels
|
7
|
+
are not available
|
8
|
+
* Always reconnect at least once, even if reconnect timeout is 0
|
9
|
+
* Catch networking errors which bubble up past redis
|
10
|
+
|
3
11
|
## 1.4.4
|
4
12
|
|
5
13
|
* Allow client to return list of slaves
|
data/README.md
CHANGED
@@ -37,6 +37,11 @@ Sentinels can also be specified using a URI. This URI syntax is required when us
|
|
37
37
|
config.cache_store = :redis_store, { master_name: "master1",
|
38
38
|
sentinels: ['sentinel://localhost:26379', 'sentinel://localhost:26380'] }
|
39
39
|
|
40
|
+
After doing the above, you might still see `#<Redis client v3.1.0 for redis://localhost:6379/0>`.
|
41
|
+
This is fine because redis-sentinel will only try to connect when it is actually required.
|
42
|
+
|
43
|
+
However, if none of the sentinel servers can be reached, a Redis::CannotConnectError will be thrown.
|
44
|
+
|
40
45
|
There are two additional options:
|
41
46
|
|
42
47
|
1. `:failover_reconnect_timeout` (seconds) will block for that long when
|
data/Rakefile
CHANGED
data/example/redis-master.conf
CHANGED
@@ -50,7 +50,7 @@ loglevel notice
|
|
50
50
|
# Specify the log file name. Also 'stdout' can be used to force
|
51
51
|
# Redis to log on the standard output. Note that if you use standard
|
52
52
|
# output for logging but daemonize, logs will be sent to /dev/null
|
53
|
-
logfile
|
53
|
+
logfile ""
|
54
54
|
|
55
55
|
# To enable logging to the system logger, just set 'syslog-enabled' to yes,
|
56
56
|
# and optionally update the other syslog parameters to suit your needs.
|
data/example/redis-slave.conf
CHANGED
@@ -50,7 +50,7 @@ loglevel notice
|
|
50
50
|
# Specify the log file name. Also 'stdout' can be used to force
|
51
51
|
# Redis to log on the standard output. Note that if you use standard
|
52
52
|
# output for logging but daemonize, logs will be sent to /dev/null
|
53
|
-
logfile
|
53
|
+
logfile ""
|
54
54
|
|
55
55
|
# To enable logging to the system logger, just set 'syslog-enabled' to yes,
|
56
56
|
# and optionally update the other syslog parameters to suit your needs.
|
@@ -15,6 +15,8 @@ class Redis::Client
|
|
15
15
|
@failover_reconnect_wait = fetch_option(options, :failover_reconnect_wait) ||
|
16
16
|
DEFAULT_FAILOVER_RECONNECT_WAIT_SECONDS
|
17
17
|
|
18
|
+
Thread.new { watch_sentinel } if sentinel? && !fetch_option(options, :async)
|
19
|
+
|
18
20
|
initialize_without_sentinel(options)
|
19
21
|
end
|
20
22
|
|
@@ -43,7 +45,7 @@ class Redis::Client
|
|
43
45
|
deadline = @failover_reconnect_timeout.to_i + Time.now.to_f
|
44
46
|
begin
|
45
47
|
block.call
|
46
|
-
rescue Redis::CannotConnectError
|
48
|
+
rescue Redis::CannotConnectError, Errno::EHOSTDOWN, Errno::EHOSTUNREACH
|
47
49
|
raise if Time.now.to_f > deadline
|
48
50
|
sleep @failover_reconnect_wait
|
49
51
|
retry
|
@@ -66,7 +68,9 @@ class Redis::Client
|
|
66
68
|
end
|
67
69
|
|
68
70
|
def discover_master
|
71
|
+
attempts = 0
|
69
72
|
while true
|
73
|
+
attempts += 1
|
70
74
|
try_next_sentinel
|
71
75
|
|
72
76
|
begin
|
@@ -81,8 +85,9 @@ class Redis::Client
|
|
81
85
|
end
|
82
86
|
rescue Redis::CommandError => e
|
83
87
|
raise unless e.message.include?("IDONTKNOW")
|
84
|
-
rescue Redis::CannotConnectError
|
88
|
+
rescue Redis::CannotConnectError, Errno::EHOSTDOWN, Errno::EHOSTUNREACH => e
|
85
89
|
# failed to connect to current sentinel server
|
90
|
+
raise e if attempts > @sentinels_options.count
|
86
91
|
end
|
87
92
|
end
|
88
93
|
end
|
@@ -95,13 +100,13 @@ class Redis::Client
|
|
95
100
|
slaves_info = current_sentinel.sentinel("slaves", @master_name)
|
96
101
|
@slaves = slaves_info.map do |info|
|
97
102
|
info = Hash[*info]
|
98
|
-
::Redis.new
|
103
|
+
::Redis.new(@options.merge(:host => info['ip'], :port => info['port'], :driver => info[:driver]))
|
99
104
|
end
|
100
105
|
|
101
106
|
break
|
102
107
|
rescue Redis::CommandError => e
|
103
108
|
raise unless e.message.include?("IDONTKNOW")
|
104
|
-
rescue Redis::CannotConnectError
|
109
|
+
rescue Redis::CannotConnectError, Errno::EHOSTDOWN, Errno::EHOSTUNREACH
|
105
110
|
# failed to connect to current sentinel server
|
106
111
|
end
|
107
112
|
end
|
@@ -139,15 +144,42 @@ class Redis::Client
|
|
139
144
|
alias call_pipeline_without_readonly_protection call_pipeline
|
140
145
|
alias call_pipeline call_pipeline_with_readonly_protection
|
141
146
|
|
147
|
+
def watch_sentinel
|
148
|
+
while true
|
149
|
+
sentinel = Redis.new(@sentinels_options[0])
|
150
|
+
|
151
|
+
begin
|
152
|
+
sentinel.psubscribe("*") do |on|
|
153
|
+
on.pmessage do |pattern, channel, message|
|
154
|
+
next if channel != "+switch-master"
|
155
|
+
|
156
|
+
master_name, old_host, old_port, new_host, new_port = message.split(" ")
|
157
|
+
|
158
|
+
next if master_name != @master_name
|
159
|
+
|
160
|
+
@options.merge!(host: new_host, port: new_port.to_i)
|
161
|
+
|
162
|
+
@logger.debug "Failover: #{old_host}:#{old_port} => #{new_host}:#{new_port}" if @logger && @logger.debug?
|
163
|
+
|
164
|
+
disconnect
|
165
|
+
end
|
166
|
+
end
|
167
|
+
rescue Redis::CannotConnectError, Errno::EHOSTDOWN, Errno::EHOSTUNREACH
|
168
|
+
try_next_sentinel
|
169
|
+
sleep 1
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
142
174
|
private
|
143
175
|
def readonly_protection_with_timeout(method, *args, &block)
|
144
176
|
deadline = @failover_reconnect_timeout.to_i + Time.now.to_f
|
145
177
|
send(method, *args, &block)
|
146
178
|
rescue Redis::CommandError => e
|
147
179
|
if e.message.include? "READONLY You can't write against a read only slave."
|
180
|
+
reconnect
|
148
181
|
raise if Time.now.to_f > deadline
|
149
182
|
sleep @failover_reconnect_wait
|
150
|
-
reconnect
|
151
183
|
retry
|
152
184
|
else
|
153
185
|
raise
|
@@ -25,7 +25,7 @@ describe Redis::Client do
|
|
25
25
|
|
26
26
|
context "new instances" do
|
27
27
|
it "should parse sentinel options" do
|
28
|
-
expect(subject.instance_variable_get(:@sentinels_options)).to
|
28
|
+
expect(subject.instance_variable_get(:@sentinels_options)).to match_array [
|
29
29
|
{:host=>"localhost", :port=>26379},
|
30
30
|
{:host=>"localhost", :port=>26380},
|
31
31
|
{:host=>"localhost", :port=>26381}
|
@@ -5,7 +5,8 @@ require "eventmachine"
|
|
5
5
|
describe Redis::Client do
|
6
6
|
context "#auto_retry_with_timeout" do
|
7
7
|
subject { described_class.new(:failover_reconnect_timeout => 3,
|
8
|
-
|
8
|
+
:failover_reconnect_wait => 0.1,
|
9
|
+
:async => true) }
|
9
10
|
context "configured wait time" do
|
10
11
|
|
11
12
|
it "uses the wait time and blocks em" do
|
metadata
CHANGED
@@ -1,97 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-sentinel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Richard Huang
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: eventmachine
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: em-synchrony
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: hiredis
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
description: another redis automatic master/slave failover solution for ruby by using
|
@@ -102,9 +102,7 @@ executables: []
|
|
102
102
|
extensions: []
|
103
103
|
extra_rdoc_files: []
|
104
104
|
files:
|
105
|
-
- .gitignore
|
106
|
-
- .ruby-gemset
|
107
|
-
- .ruby-version
|
105
|
+
- ".gitignore"
|
108
106
|
- CHANGELOG.md
|
109
107
|
- CONTRIBUTING.md
|
110
108
|
- Gemfile
|
@@ -137,17 +135,17 @@ require_paths:
|
|
137
135
|
- lib
|
138
136
|
required_ruby_version: !ruby/object:Gem::Requirement
|
139
137
|
requirements:
|
140
|
-
- -
|
138
|
+
- - ">="
|
141
139
|
- !ruby/object:Gem::Version
|
142
140
|
version: '0'
|
143
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
144
142
|
requirements:
|
145
|
-
- -
|
143
|
+
- - ">="
|
146
144
|
- !ruby/object:Gem::Version
|
147
145
|
version: '0'
|
148
146
|
requirements: []
|
149
147
|
rubyforge_project:
|
150
|
-
rubygems_version: 2.2.
|
148
|
+
rubygems_version: 2.2.2
|
151
149
|
signing_key:
|
152
150
|
specification_version: 4
|
153
151
|
summary: another redis automatic master/slave failover solution for ruby by using
|
data/.ruby-gemset
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
redis-sentinel
|
data/.ruby-version
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
ruby-2.0.0
|