Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you handle failed redis connections

I am using the Redis Windows implementation together with StackExchange.Redis client. My question is this, how do you handle reconnection attempts if the initial connection fails. I am thinking of the worst case scenario when all Redis master and slave services are down. The problem is that every time my app needs something from cache it will try and reconnect to Redis (if the intial connection failed) and this is very time consuming. My factory class looks like this:

 private ConnectionMultiplexer GetConnection()
        {

            if (connection != null && connection.IsConnected) return connection;

            lock (_lock)
            {
                if (connection != null && connection.IsConnected) return connection;

                if (connection != null)
                {
                    logger.Log("Redis connection disconnected. Disposing connection...");
                    connection.Dispose();
                }

                logger.Log("Creating new instance of Redis Connection");


                connection = ConnectionMultiplexer.Connect(connectionString.Value);
            }

            return connection;

        }

        public IDatabase Database(int? db = null)
        {
            try
            {
                return !redisConnectionValid ? null : GetConnection().GetDatabase(db ?? settings.DefaultDb);
            }
            catch (Exception ex)
            {
                redisConnectionValid = false;
                logger.Log(Level.Error, String.Format("Unable to create Redis connection: {0}", ex.Message));
                return null;
            }
        }

You can see that I am using a singleton pattern for creating the connection. If the initial connection fails I am setting a flag (redisConnectionValid) so that subsequent calls are prevented from attempting to recreate the connection (which takes approx 5-10 seconds). Is there a better approach than this? Our design goal is for our application to work as normal even if Redis caching is unavailable. We do not want the app performance to suffer because of continous Redis connection attempts that will ultimately fail/time out in worst case scenarios.

like image 638
Myles J Avatar asked Nov 24 '14 10:11

Myles J


People also ask

How do I handle Redis connection?

Redis accepts clients connections on the configured TCP port and on the Unix socket if enabled. When a new client connection is accepted the following operations are performed: The client socket is put in the non-blocking state since Redis uses multiplexing and non-blocking I/O.

What happens if Redis fails?

If the connection has failed, or is closed, for standard cache ops, the (Redis)CacheManager could return an instance of RedisCache for getCache(String name) that always returns null (indicating a Cache miss on an entry), thus passing through to the underlying data store.

How does Redis handle multiple connections?

Large number of connectionsRedis is a single-threaded process based on an event loop where incoming client requests are handled sequentially. That means the response time of a given client becomes longer as the number of connected clients increases.

How many connections Redis can handle?

Redis can handle many connections, and by default, Redis has a maximum number of client connections set at 10,000 connections. You can set the maximum number of client connections you want the Redis server to accept by altering the maxclient from within the redis. conf file.


1 Answers

You should let StackExchange.Redis handle the reconnect, rather than checking IsConnected yourself. Here is the pattern we recommend:

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => {
    return ConnectionMultiplexer.Connect("mycache.redis.cache.windows.net,abortConnect=false,ssl=true,password=...");
});

public static ConnectionMultiplexer Connection {
    get {
        return lazyConnection.Value;
    }
}

Note that "abortConnect" is set to "false". This means if the first connection attempt fails, ConnectionMultiplexer will retry in the background rather than throwing an exception.

like image 187
Mike Harder Avatar answered Oct 30 '22 13:10

Mike Harder