nogara-redis_failover 0.9.7.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Changes.md CHANGED
@@ -1,5 +1,7 @@
1
- HEAD
1
+ 1.0.0
2
2
  -----------
3
+ ** NOTE: This version of redis_failover requires that you upgrade your clients and Node Managers at the same time.
4
+
3
5
  - redis_failover now supports distributed monitoring among the Node Managers! Previously, the Node Managers were only used
4
6
  as a means of redundancy in case a particular node manager crashed. Starting with version 1.0 of redis_failover, the Node
5
7
  Managers will all periodically report their health report/snapshots. The primary Node Manager will utilize a configurable
@@ -8,6 +10,7 @@ Managers will all periodically report their health report/snapshots. The primary
8
10
  a single strategy is provided that takes into account the average latency of the last health check to the redis server.
9
11
  - Improved handling of underlying ZK client connection in RedisFailover::NodeManager
10
12
  - Add support for passing in an existing ZK client instance to RedisFailover::Cient.new
13
+ - Reduce unnecessary writes to ZK
11
14
 
12
15
  0.9.7.2
13
16
  -----------
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/ryanlecompte/redis_failover.png?branch=master)](http://travis-ci.org/ryanlecompte/redis_failover)
4
4
 
5
- redis_failover attempts to provides a full automatic master/slave failover solution for Ruby. Redis does not currently provide
5
+ redis_failover provides a full automatic master/slave failover solution for Ruby. Redis does not currently provide
6
6
  an automatic failover capability when configured for master/slave replication. When the master node dies,
7
7
  a new master must be manually brought online and assigned as the slave's new master. This manual
8
8
  switch-over is not desirable in high traffic sites where Redis is a critical part of the overall
@@ -321,6 +321,10 @@ module RedisFailover
321
321
  logger.debug { "Caught #{ex.class} '#{ex.message}' - reopening ZK client" }
322
322
  @zk.reopen
323
323
  retry
324
+ rescue *ZK_ERRORS => ex
325
+ logger.warn { "Caught #{ex.class} '#{ex.message}' - retrying" }
326
+ sleep(RETRY_WAIT_TIME)
327
+ retry
324
328
  end
325
329
 
326
330
  # Builds new Redis clients for the specified nodes.
@@ -12,15 +12,11 @@ module RedisFailover
12
12
  # Number of seconds to wait before retrying bootstrap process.
13
13
  TIMEOUT = 5
14
14
  # Number of seconds for checking node snapshots.
15
- CHECK_INTERVAL = 10
15
+ CHECK_INTERVAL = 5
16
16
  # Number of max attempts to promote a master before releasing master lock.
17
17
  MAX_PROMOTION_ATTEMPTS = 3
18
-
19
- # ZK Errors that the Node Manager cares about.
20
- ZK_ERRORS = [
21
- ZK::Exceptions::LockAssertionFailedError,
22
- ZK::Exceptions::InterruptedSession
23
- ].freeze
18
+ # Latency threshold for recording node state.
19
+ LATENCY_THRESHOLD = 0.5
24
20
 
25
21
  # Errors that can happen during the node discovery process.
26
22
  NODE_DISCOVERY_ERRORS = [
@@ -436,6 +432,12 @@ module RedisFailover
436
432
  write_state(redis_nodes_path, encode(current_nodes))
437
433
  end
438
434
 
435
+ # Writes the current monitored list of redis nodes. This method is always
436
+ # invoked by all running node managers.
437
+ def write_current_monitored_state
438
+ write_state(current_state_path, encode(node_availability_state), :ephemeral => true)
439
+ end
440
+
439
441
  # @return [String] root path for current node manager state
440
442
  def current_state_root
441
443
  "#{@root_znode}/manager_node_state"
@@ -496,21 +498,31 @@ module RedisFailover
496
498
  # @param [Symbol] state the node state
497
499
  # @param [Integer] latency an optional latency
498
500
  def update_current_state(node, state, latency = nil)
501
+ old_unavailable = @monitored_unavailable.dup
502
+ old_available = @monitored_available.dup
503
+
499
504
  case state
500
505
  when :unavailable
501
- @monitored_unavailable |= [node]
502
- @monitored_available.delete(node)
506
+ unless @monitored_unavailable.include?(node)
507
+ @monitored_unavailable << node
508
+ @monitored_available.delete(node)
509
+ write_current_monitored_state
510
+ end
503
511
  when :available
504
- @monitored_available[node] = latency
505
- @monitored_unavailable.delete(node)
512
+ last_latency = @monitored_available[node]
513
+ if last_latency.nil? || (latency - last_latency) > LATENCY_THRESHOLD
514
+ @monitored_available[node] = latency
515
+ @monitored_unavailable.delete(node)
516
+ write_current_monitored_state
517
+ end
506
518
  else
507
519
  raise InvalidNodeStateError.new(node, state)
508
520
  end
509
-
510
- # flush ephemeral current node manager state
511
- write_state(current_state_path,
512
- encode(node_availability_state),
513
- :ephemeral => true)
521
+ rescue => ex
522
+ # if an error occurs, make sure that we rollback to the old state
523
+ @monitored_unavailable = old_unavailable
524
+ @monitored_available = old_available
525
+ raise
514
526
  end
515
527
 
516
528
  # Fetches each currently running node manager's view of the
@@ -61,11 +61,19 @@ module RedisFailover
61
61
  REDIS_ERRORS << Redis::BaseError if Redis.const_defined?('BaseError')
62
62
  REDIS_ERRORS.freeze
63
63
 
64
+ # ZK Errors
65
+ ZK_ERRORS = [
66
+ ZK::Exceptions::LockAssertionFailedError,
67
+ ZK::Exceptions::InterruptedSession,
68
+ ZK::Exceptions::Retryable,
69
+ Zookeeper::Exceptions::ContinuationTimeoutError
70
+ ].freeze
71
+
64
72
  # Full set of errors related to connectivity.
65
73
  CONNECTIVITY_ERRORS = [
66
74
  RedisFailover::Error,
67
- ZK::Exceptions::InterruptedSession,
68
- REDIS_ERRORS
75
+ REDIS_ERRORS,
76
+ ZK_ERRORS
69
77
  ].flatten.freeze
70
78
 
71
79
  # Symbolizes the keys of the specified hash.
@@ -1,3 +1,3 @@
1
1
  module RedisFailover
2
- VERSION = '0.9.7.4'
2
+ VERSION = '1.0.0'
3
3
  end
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nogara-redis_failover
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.7.4
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-08 00:00:00.000000000 Z
12
+ date: 2012-11-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: redis