2014-11-24 3 views
4

Я использую реализацию Redis Windows вместе с клиентом StackExchange.Redis. Мой вопрос в том, как вы справляетесь с попытками повторного соединения, если исходное соединение терпит неудачу. Я думаю о худшем случае, когда все мастера Redis и подчиненные службы опущены. Проблема в том, что каждый раз, когда мое приложение нуждается в чем-то из кеша, оно будет пытаться подключиться к Redis (если соединение не выполнено), и это очень трудоемко. Мой класс фабрики выглядит следующим образом:Как обрабатывать неудачные соединения redis

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; 
      } 
     } 

Вы можете видеть, что я использую одноэлементный шаблон для создания соединения. Если исходное соединение не выполняется, я устанавливаю флаг (redisConnectionValid), чтобы последующие вызовы не пытались воссоздать соединение (которое занимает около 5-10 секунд). Есть ли лучший подход, чем этот? Наша цель дизайна - наше приложение работает нормально, даже если кэширование Redis недоступно. Мы не хотим, чтобы производительность приложения страдает из-за постоянных попыток подключения Redis, которые в конечном итоге потерпят неудачу/тайм-аут в худшем случае.

ответ

16

Вы должны позволить StackExchange.Redis обрабатывать соединение повторно, а не проверять IsConnected самостоятельно. Вот пример, который мы рекомендуем:

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; 
    } 
} 

Обратите внимание, что для параметра «abortConnect» установлено значение «false». Это означает, что если первая попытка подключения завершилась неудачей, ConnectionMultiplexer повторит попытку в фоновом режиме вместо исключения исключения.

+0

В другой статье я вижу, что «вызов будет успешным, даже если соединение с кэшем Redis не установлено». Если исключение не выбрасывается, то как вы устанавливаете, что соединение потерпело неудачу? Вы запросили бы свойство IsConnected до попытки доступа к кешу? –

+2

Вызов Connect() не будет бросать, но если вы попытаетесь выполнить операцию кэширования (например, StringGet()), он будет метать. И вашему приложению уже нужно обрабатывать исключения, вызванные кеш-операциями. –

Смежные вопросы