Redis is a popular key-value store that is fast, reliable and simple to administer. While Redis asynchronous master-slave replication is well known, Sentinel seems to be a little known feature. Sentinel is a built-in feature in v2.6+ that provides an automatic failover mechanism, i.e. promotion of a slave to replace a failing master, reconfiguring other slaves to use a new master and informing client applications about the new address to use when connecting to a master.

Limitations

The official docs note that Sentinel is a work in progress. It's important to understand Sentinel's operating parameters and its limitations as a high availability (HA) solution for your particular environment. For that, I defer you to these excellent posts:


Setup

A prerequisite for using Sentinel for automatic failover is to have a master-slave replication setup. Both replication and Sentinel are easy to setup and well documented in the official docs.

Once you have everything setup, you then need to configure your Redis clients (web apps, queues etc) to connect to the Sentinel instances instead of directly to a master. The Sentinel instances will then report back to the clients on the appropriate address to use to connect to an available master.

Client Library Support

Redis Sentinel support in the various clients libraries seems limited at this time. Some client libraries have extensions that provide Sentinel support. You could implement Sentinel support in your desired client library by following the Sentinel Client Guidelines.

Listed below are examples for configuring clients when using Ruby & Node.js. The examples assume a YAML config similar to this:

redis:
  master_name: master-name
  sentinels:
    - host: sentinel1.example.com
      port: 26380
    - host: sentinel1.example.com
      port: 26381
    - host: sentinel2.example.com
      port: 26380
    - host: sentinel2.example.com
      port: 26381

master_name should match the name you use in the sentinel.conf and the host & port entries should match the hosts and ports that you run Sentinels on.

Ruby

At the time of writing, the redis-rb client doesn't yet support Sentinel. redis-sentinel extends redis-rb to provide the necessary support and acts as a drop-in replacement anywhere a redis-rb client is expected.

# Ruby Examples

# Redis.new works as expected with the added benefit of clients being informed
# when a new master is elected
redis_config = YAML.load_file('/path/to/redis_config.yml')['redis']
redis = Redis.new(redis_config)
redis.info

# Configure Sidekiq in Ruby on Rails (config/initializers/sidekiq.rb)
require 'redis/namespace'

redis_config = YAML.load_file('/path/to/redis_config.yml')['redis']
size = options[:size] || (Sidekiq.server? ? (Sidekiq.options[:concurrency] + 2) : 5)
namespace = 'sidekiq'
timeout = 1

Sidekiq.configure_server do |config|
  redis = ConnectionPool.new(:timeout => timeout, :size => size) do
    Redis::Namespace.new(namespace, :redis => Redis.new(redis_config))
  end

  config.redis = redis
end

Sidekiq.configure_client do |config|
  redis = ConnectionPool.new(:timeout => timeout, :size => size) do
    Redis::Namespace.new(namespace, :redis => Redis.new(redis_config))
  end

  config.redis = redis
end


Node.js

At the time of writing, the node_redis client doesn't yet support Sentinel. node-redis-sentinel extends noderedis to provide the necessary support and acts as a drop-in replacement anywhere a noderedis client is expected.

# CoffeeScript Examples

yaml = require('js-yaml') # https://github.com/nodeca/js-yaml
redis = require('redis') # https://github.com/mranney/node_redis
sentinel = require('redis-sentinel') # https://github.com/ortoo/node-redis-sentinel

redis_config = require('/path/to/redis_config.yml')
masterName = redis_config.master_name
sentinels = redis_config.sentinels
opts = {} # standard node_redis client options

redisClient = sentinel.createClient(sentinels, masterName, opts)