Class: RedisFailover::Client
- Inherits:
-
Object
- Object
- RedisFailover::Client
- Includes:
- Util
- Defined in:
- lib/redis_failover/client.rb
Overview
Redis failover-aware client. RedisFailover::Client is a wrapper over a set of underlying redis clients, which means all normal redis operations can be performed on an instance of this class. The class only requires a set of ZooKeeper server addresses to function properly. The client will automatically retry failed operations, and handle failover to a new master. The client registers and listens for watcher events from the Node Manager. When these events are received, the client fetches the latest set of redis nodes from ZooKeeper and rebuilds its internal Redis clients appropriately. RedisFailover::Client also directs write operations to the master, and all read operations to the slaves.
Constant Summary collapse
- ZNODE_UPDATE_TIMEOUT =
Maximum allowed elapsed time between notifications from the Node Manager. When this timeout is reached, the client will raise a NoNodeManagerError and purge its internal redis clients.
9
- RETRY_WAIT_TIME =
Amount of time to sleep before retrying a failed operation.
3
Constants included from Util
Util::CONNECTIVITY_ERRORS, Util::DEFAULT_ZNODE_PATH, Util::REDIS_ERRORS, Util::REDIS_READ_OPS, Util::UNSUPPORTED_OPS
Instance Method Summary collapse
-
#client ⇒ Object
Resque wants to use Resque.redis.reconnect to recreate all connections.
-
#current_master ⇒ String
Retrieves the current redis master.
-
#current_slaves ⇒ Array<String>
Retrieves the current redis slaves.
-
#initialize(options = {}) {|_self| ... } ⇒ RedisFailover::Client
constructor
Creates a new failover redis client.
-
#inspect ⇒ String
(also: #to_s)
A string representation of the client.
-
#manual_failover(options = {}) ⇒ Object
Force a manual failover to a new server.
-
#method_missing(method, *args, &block) ⇒ Object
Dispatches redis operations to master/slaves.
-
#on_node_change(&callback) ⇒ Object
Specifies a callback to invoke when the current redis node list changes.
-
#reconnect ⇒ Object
Reconnect will first perform a shutdown of the underlying redis clients.
-
#respond_to_missing?(method, include_private) ⇒ Boolean
Determines whether or not an unknown method can be handled.
-
#shutdown ⇒ Object
Gracefully performs a shutdown of this client.
Methods included from Util
#decode, #different?, #encode, logger, #logger, logger=, #symbolize_keys
Constructor Details
#initialize(options = {}) {|_self| ... } ⇒ RedisFailover::Client
Creates a new failover redis client.
53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/redis_failover/client.rb', line 53 def initialize( = {}) Util.logger = [:logger] if [:logger] @master = nil @slaves = [] @node_addresses = {} @lock = Monitor.new @current_client_key = "current-client-#{self.object_id}" yield self if block_given? () setup_zk build_clients end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object
Dispatches redis operations to master/slaves.
89 90 91 92 93 94 95 |
# File 'lib/redis_failover/client.rb', line 89 def method_missing(method, *args, &block) if redis_operation?(method) dispatch(method, *args, &block) else super end end |
Instance Method Details
#client ⇒ Object
Resque wants to use Resque.redis.reconnect to recreate all connections. So we provide ourselves as a client to receive the "reconnect" message
70 71 72 |
# File 'lib/redis_failover/client.rb', line 70 def client self end |
#current_master ⇒ String
Retrieves the current redis master.
147 148 149 150 |
# File 'lib/redis_failover/client.rb', line 147 def current_master master = @lock.synchronize { @master } address_for(master) end |
#current_slaves ⇒ Array<String>
Retrieves the current redis slaves.
155 156 157 158 |
# File 'lib/redis_failover/client.rb', line 155 def current_slaves slaves = @lock.synchronize { @slaves } addresses_for(slaves) end |
#inspect ⇒ String Also known as: to_s
Returns a string representation of the client.
107 108 109 |
# File 'lib/redis_failover/client.rb', line 107 def inspect "#<RedisFailover::Client (master: #{master_name}, slaves: #{slave_names})>" end |
#manual_failover(options = {}) ⇒ Object
Force a manual failover to a new server. A specific server can be specified via options. If no options are passed, a random slave will be selected as the candidate for the new master.
119 120 121 122 |
# File 'lib/redis_failover/client.rb', line 119 def manual_failover( = {}) ManualFailover.new(@zk, ).perform self end |
#on_node_change(&callback) ⇒ Object
Specifies a callback to invoke when the current redis node list changes.
84 85 86 |
# File 'lib/redis_failover/client.rb', line 84 def on_node_change(&callback) @on_node_change = callback end |
#reconnect ⇒ Object
Reconnect will first perform a shutdown of the underlying redis clients. Next, it attempts to reopen the ZooKeeper client and re-create the redis clients after it fetches the most up-to-date list from ZooKeeper.
138 139 140 141 142 |
# File 'lib/redis_failover/client.rb', line 138 def reconnect purge_clients @zk ? @zk.reopen : setup_zk build_clients end |
#respond_to_missing?(method, include_private) ⇒ Boolean
Determines whether or not an unknown method can be handled.
102 103 104 |
# File 'lib/redis_failover/client.rb', line 102 def respond_to_missing?(method, include_private) redis_operation?(method) || super end |
#shutdown ⇒ Object
Gracefully performs a shutdown of this client. This method is mostly useful when the client is used in a forking environment. When a fork occurs, you can call this method in an after_fork hook, and then create a new instance of the client. The underlying ZooKeeper client and redis clients will be closed.
129 130 131 132 133 |
# File 'lib/redis_failover/client.rb', line 129 def shutdown @zk.close! if @zk @zk = nil purge_clients end |