У меня есть следующие проблемы в нашей производственной среде (веб-ферма - 4 узла, поверх нее балансировщик нагрузки):
1) Timeout performing HGET key, inst: 3, queue: 29, qu=0, qs=29, qc=0, wr=0/0
at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor``1 processor, ServerEndPoint server) in ConnectionMultiplexer.cs:line 1699
Это происходит 3-10 раз в минуту
2) No connection is available to service this operation: HGET key at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor``1 processor, ServerEndPoint server) in ConnectionMultiplexer.cs:line 1666
Я попытался реализовать, как предложил Марк (возможно, я неправильно это интерпретировал) - лучше иметь меньше подключений к Redis, чем несколько. Я сделал следующую реализацию:
public class SeRedisConnection
{
private static ConnectionMultiplexer _redis;
private static readonly object SyncLock = new object();
public static IDatabase GetDatabase()
{
if (_redis == null || !_redis.IsConnected || !_redis.GetDatabase().IsConnected(default(RedisKey)))
{
lock (SyncLock)
{
try
{
var configurationOptions = new ConfigurationOptions
{
AbortOnConnectFail = false
};
configurationOptions.EndPoints.Add(new DnsEndPoint(ConfigurationHelper.CacheServerHost,
ConfigurationHelper.CacheServerHostPort));
_redis = ConnectionMultiplexer.Connect(configurationOptions);
}
catch (Exception ex)
{
IoC.Container.Resolve<IErrorLog>().Error(ex);
return null;
}
}
}
return _redis.GetDatabase();
}
public static void Dispose()
{
_redis.Dispose();
}
}
На самом деле dispose сейчас не используется. Также у меня есть некоторые особенности реализации, которые могут вызвать такое поведение (я использую только хэши): 1. Добавить, удалить хэши - асинхронно 2. Получить -синхронно
Может ли кто-нибудь помочь мне, как избежать такого поведения?
Заранее большое спасибо!
РЕШЕНО: увеличение времени ожидания подключения клиента после оценки возможностей сети.
ОБНОВЛЕНИЕ 2. На самом деле это не решило проблему. Когда объем кеша начинает увеличиваться, например. от 2гб. Затем я увидел ту же картину, на самом деле эти тайм-ауты происходили примерно каждые 5 минут. И наши сайты замораживались на некоторое время каждые 5 минут, пока не закончилась операция форка. Затем я узнал, что есть возможность делать форк (сохранять на диск) каждые x секунд:
save 900 1
save 300 10
save 60 10000
В моем случае это было "сохранить 300 10" - сохранять каждые 5 минут, если произошло не менее 10 обновлений. Также я узнал, что «вилка» может быть очень дорогой. Закомментированный раздел «сохранить» вообще решил проблему. Мы можем прокомментировать раздел «сохранить», так как мы используем только Redis в качестве «кеша в памяти» — нам не нужно какое-либо постоянство. Вот конфигурация наших кеш-серверов "Redis 2.4.6" порт Windows: https://github.com/rgl/redis/downloads
Возможно, это было решено в последних версиях порта Redis для Windows в MSOpentech: http://msopentech.com/blog/2013/04/22/redis-on-windows-stable-and-reliable/, но я еще не проверял.
В любом случае, StackExchange.Redis не имеет ничего общего с этой проблемой, и благодаря Marc Gravell он работает довольно стабильно в нашей производственной среде.
ПОСЛЕДНЕЕ ОБНОВЛЕНИЕ: Redis — это однопоточное решение. Оно очень быстрое, но когда дело доходит до освобождения памяти (удаление устаревших или просроченных элементов), проблемы возникают из-за того, что один поток должен восстановить память (это не быстрая операция - какой бы алгоритм ни использовался), и один и тот же поток должен обрабатывать операции GET, SET. Конечно, это происходит, когда мы говорим о средненагруженной производственной среде. Даже если вы используете кластер с ведомыми устройствами, при достижении барьера памяти он будет вести себя так же.