nogara-redis_failover 0.9.7.4 → 1.0.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/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