Высокая загрузка ЦП после использования кеша Redis в асинхронном режиме С#

Я использую https://github.com/StackExchange/StackExchange.Redis. (StackExchange.Redis.StrongName.1.2.1)

У меня есть такая асинхронная функция, которая заставляет процессор загружаться на 100% и начинает получать ошибку тайм-аута через 4-5 минут после обслуживания 400 запросов.

 public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getItemCallback) where T : class
         {
             T item = null;
             IDatabase cache = Connection.GetDatabase();
             var cacheValue = await cache.StringGetAsync(cacheKey);
            if (cacheValue.IsNull)
            {
                item = await getItemCallback();
                await cache.StringSetAsync(cacheKey, JsonConvert.SerializeObject(item));
            }
            else
            {
                item = await Task.Factory.StartNew(() => JsonConvert.DeserializeObject<T>(cacheValue));
            }
             return item;
         }

Если я перестану использовать кэш Redis и верну прямые значения из БД, я смогу выполнить загрузку 1300 запросов за 2 минуты 20 секунд. Высокая загрузка процессора все еще в состоянии завершить загрузку.

 public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getItemCallback) where T : class
         {
            return await getItemCallback();
         }

Если я просто изменю функцию ниже на getDatabase и ничего не сделаю. это приводит к тому, что ЦП сразу переходит на 100% и зависает после 200 запросов за 2 минуты, что связано с высокой загрузкой ЦП.

 public async Task<T> GetOrSetAsync<T>(string cacheKey, Func<Task<T>> getItemCallback) where T : class
         {
           IDatabase cache = Connection.GetDatabase();
            return await getItemCallback();
         }

Но вопрос в том, почему использование процессора увеличилось только с добавлением

Кэш IDatabase = Connection.GetDatabase(); ?


person Shiv    schedule 06.04.2017    source источник


Ответы (1)


Как реализовано ваше свойство «Соединение»? Создает ли он новое соединение с Redis при каждом вызове? Если да, то это не рекомендуется. Вы должны использовать одно соединение для ваших вызовов.

private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
    return ConnectionMultiplexer.Connect("<your connection string here>");
});

public static ConnectionMultiplexer Connection
{
    get
    {
        return lazyConnection.Value;
    }
}
person Carl Dacosta    schedule 07.04.2017
comment
Хотя ленивый init использовал его, он не был статичным, класс, содержащий его, был областью действия instanceperlifetime, которую я изменил на singleton. он работает так же быстро, как локальный кеш :) - person Shiv; 08.04.2017