Почему соединения с Azure Redis Cache так высоки?

Я использую Redis Cache Azure в сценарии с высокой нагрузкой для одного компьютера, запрашивающего кэш. Эта машина примерно получает и устанавливает около 20 предметов в секунду. Днем это увеличивается, а ночью меньше.

Пока все работает нормально. Сегодня я понял, что показатель "Подключенные клиенты" чрезвычайно высок, хотя у меня есть только 1 клиент, который просто постоянно получает и устанавливает элементы. Вот скриншот метрики, которую я имею в виду:Redis Cache Подключенные клиенты

Мой код выглядит так:

public class RedisCache<TValue> : ICache<TValue>
{
    private IDatabase cache;
    private ConnectionMultiplexer connectionMultiplexer;

    public RedisCache()
    {
        ConfigurationOptions config = new ConfigurationOptions();
        config.EndPoints.Add(GlobalConfig.Instance.GetConfig("RedisCacheUrl"));
        config.Password = GlobalConfig.Instance.GetConfig("RedisCachePassword");
        config.ConnectRetry = int.MaxValue; // retry connection if broken
        config.KeepAlive = 60; // keep connection alive (ping every minute)
        config.Ssl = true;
        config.SyncTimeout = 8000; // 8 seconds timeout for each get/set/remove operation
        config.ConnectTimeout = 20000; // 20 seconds to connect to the cache

        connectionMultiplexer = ConnectionMultiplexer.Connect(config);
        cache = connectionMultiplexer.GetDatabase();
    }

    public virtual bool Add(string key, TValue item)
    {
        return cache.StringSet(key, RawSerializationHelper.Serialize(item));
    }

Я не создаю более одного экземпляра этого класса, так что это не проблема. Может быть, я неправильно понимаю метрику соединений, и на самом деле они означают, сколько раз я обращаюсь к кешу, однако, на мой взгляд, это не имеет смысла. Любые идеи, или кто-нибудь с похожей проблемой?

1 ответ

Решение

StackExchange.Redis имел состояние гонки, которое могло привести к утечке соединений при некоторых условиях. Это было исправлено в сборке 1.0.333 или новее.

Если вы хотите подтвердить, что это проблема, к которой вы обращаетесь, получите аварийный дамп вашего клиентского приложения и посмотрите на объекты в куче в отладчике. Найдите большое количество объектов StackExchange.Redis.ServerEndPoint.

Кроме того, у нескольких пользователей были ошибки в коде, которые приводили к утечке объектов соединения. Это часто происходит потому, что их код пытается воссоздать объект ConnectionMultiplexer, если они видят сбои или отключенное состояние. На самом деле нет необходимости воссоздавать ConnectionMultiplexer, поскольку он имеет внутреннюю логику для воссоздания соединения по мере необходимости. Просто убедитесь, что для abortConnect установлено значение false в строке подключения.

Если вы решили воссоздать объект подключения, убедитесь, что удалили старый объект, прежде чем выпускать все ссылки на него.

Вот образец, который мы рекомендуем:


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

        public static ConnectionMultiplexer Connection {
            get {
                return lazyConnection.Value;
            }
        }
Другие вопросы по тегам