Тайм-аут StackExchange.Redis и нет доступного соединения для обслуживания этой операции

У меня есть следующие проблемы в нашей производственной среде (веб-ферма - 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. Конечно, это происходит, когда мы говорим о средненагруженной производственной среде. Даже если вы используете кластер с ведомыми устройствами, при достижении барьера памяти он будет вести себя так же.


person George Anisimov    schedule 08.04.2014    source источник
comment
Если вы используете Asp.Net, попробуйте сослаться на мой ответ в stackoverflow.com/questions/25416562/ это исправление ошибок тайм-аута очереди для меня, т. е. ваша проблема 1 и 2. Я пробовал другие способы (одиночки и блокировки), чтобы поддерживать меньше соединений, но безуспешно! Надеюсь, это поможет   -  person Sharat Pandavula    schedule 20.09.2014
comment
Очень полезно, спасибо! На самом деле я изменил время между сохранениями, чтобы убедиться, что никогда не будет огромной очереди элементов для сохранения на диск, что может привести к достаточной задержке для тайм-аута запроса.   -  person tommed    schedule 12.02.2015
comment
Эй, Томм, к сожалению, мы вообще перестали использовать Redis, поскольку он доказал свою однопоточную архитектуру с тайм-аутами. Пример: у нас было 32 ГБ / 4 узла кеш-серверов (кластеризация). Когда достигнут максимальный порог памяти, Redis пытается освободить память, а затем происходит тайм-аут. Я признаю, что мы активно используем Redis в нашем производстве, он работал отлично, пока не был достигнут порог памяти. Поэтому мы выбрали другое решение для многопоточного кэширования. Но, как я уже сказал, возможно, для вашего объема и конфигурации это сработает, но вы должны сделать некоторые нагрузочные тесты, когда будет достигнут порог памяти.   -  person George Anisimov    schedule 16.02.2015
comment
Спасибо, нам нужно обрабатывать 10 миллионов записей в день, что требует нескольких GET для Redis на каждую запись. Большинство из них поступает в час пик. Мы согласились с тем, что будут времена, когда Redis синхронизируется с диском и блокирует единственный поток, и просто терпеливо ждет, пока это не будет завершено. После настройки времени синхронизации ввода-вывода, чтобы ограничить эту проблему (** за счет повышения риска потери записей), мы нашли хороший баланс, при котором Redis работает хорошо. Жаль, что нет отдельного потока для синхронизации ввода-вывода!!   -  person tommed    schedule 09.03.2015
comment
@GeorgeAnisimov Итак, мы выбрали другое решение для многопоточного кэширования. Можете ли вы предоставить нам это решение?   -  person mohammed sameeh    schedule 07.12.2017
comment
@mohammedsameeh - конечно, это был microsoft.appfabric - но это было давно - возможно, Redis стал лучше :)   -  person George Anisimov    schedule 11.04.2018


Ответы (1)


Похоже, что в большинстве случаев это исключение является проблемой клиента. Предыдущие версии StackExchange.Redis напрямую использовали сокет Win32, что иногда оказывало негативное влияние. Вероятно, внутренняя маршрутизация Asp.net как-то связана с этим.
Хорошая новость заключается в том, что сетевая инфраструктура StackExchange.Redis недавно была полностью переписана. Последняя версия 2.0.513. Попробуйте, и есть большая вероятность, что ваша проблема исчезнет.

person Bennie Zhitomirsky    schedule 11.11.2018
comment
К сожалению, я все еще сталкиваюсь с этой проблемой, используя последнюю версию StackExchange.Redis (v2.0.519), включенную в последнюю версию (v4.0.1) Microsoft.Web.RedisSessionStateProvider. Как человек, который был невероятно взволнован этим обновлением, я до сих пор нахожу, что оно не решило мои проблемы. Я внес коррективы в наши настройки ThreadPool, чтобы убедиться, что нас не ограничивают низкие минимумы, оценил наши показатели кэша в Azure, но по-прежнему вижу много тайм-аутов в функции EVAL. - person Kaitebug; 17.12.2018
comment
@Kaitebug Я знаю, что этому почти год, но вы когда-нибудь находили для него решение? Мы используем последнюю версию StackExchange.Redis (2.0.601.3402) и пробовали то же самое, что вы перечислили здесь, но все еще постоянно сталкиваемся с этими проблемами после обновления. - person blizz; 16.10.2019