Я реализую слой кэширования Redis с помощью клиента Stackexchange Redis, а производительность прямо сейчас граничит с непригодными.StackExchange клиент redis очень медленный по сравнению с эталонными тестами
У меня локальная среда, в которой веб-приложение и сервер redis работают на одном компьютере. Я побежал тест бенчмарк Redis против моего сервера Redis и результаты были на самом деле очень хорошо (я просто в том числе набор и получить работу в моем подправить):
C:\Program Files\Redis>redis-benchmark -n 100000
====== PING_INLINE ======
100000 requests completed in 0.88 seconds
50 parallel clients
3 bytes payload
keep alive: 1
====== SET ======
100000 requests completed in 0.89 seconds
50 parallel clients
3 bytes payload
keep alive: 1
99.70% <= 1 milliseconds
99.90% <= 2 milliseconds
100.00% <= 3 milliseconds
111982.08 requests per second
====== GET ======
100000 requests completed in 0.81 seconds
50 parallel clients
3 bytes payload
keep alive: 1
99.87% <= 1 milliseconds
99.98% <= 2 milliseconds
100.00% <= 2 milliseconds
124069.48 requests per second
Итак, в соответствии с критериями, я смотрю на более 100 000 наборов и 100 000 посещений в секунду. Я написал модульное тестирование, чтобы сделать 300000 комплект/получает:
private string redisCacheConn = "localhost:6379,allowAdmin=true,abortConnect=false,ssl=false";
[Fact]
public void PerfTestWriteShortString()
{
CacheManager cm = new CacheManager(redisCacheConn);
string svalue = "t";
string skey = "testtesttest";
for (int i = 0; i < 300000; i++)
{
cm.SaveCache(skey + i, svalue);
string valRead = cm.ObtainItemFromCacheString(skey + i);
}
}
При этом используется следующий класс для выполнения операций Redis с помощью клиента Stackexchange:
using StackExchange.Redis;
namespace Caching
{
public class CacheManager:ICacheManager, ICacheManagerReports
{
private static string cs;
private static ConfigurationOptions options;
private int pageSize = 5000;
public ICacheSerializer serializer { get; set; }
public CacheManager(string connectionString)
{
serializer = new SerializeJSON();
cs = connectionString;
options = ConfigurationOptions.Parse(connectionString);
options.SyncTimeout = 60000;
}
private static readonly Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(options));
private static ConnectionMultiplexer Connection => lazyConnection.Value;
private static IDatabase cache => Connection.GetDatabase();
public string ObtainItemFromCacheString(string cacheId)
{
return cache.StringGet(cacheId);
}
public void SaveCache<T>(string cacheId, T cacheEntry, TimeSpan? expiry = null)
{
if (IsValueType<T>())
{
cache.StringSet(cacheId, cacheEntry.ToString(), expiry);
}
else
{
cache.StringSet(cacheId, serializer.SerializeObject(cacheEntry), expiry);
}
}
public bool IsValueType<T>()
{
return typeof(T).IsValueType || typeof(T) == typeof(string);
}
}
}
Моя JSON сериализатор только с помощью Newtonsoft.JSON :
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Caching
{
public class SerializeJSON:ICacheSerializer
{
public string SerializeObject<T>(T cacheEntry)
{
return JsonConvert.SerializeObject(cacheEntry, Formatting.None,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
public T DeserializeObject<T>(string data)
{
return JsonConvert.DeserializeObject<T>(data, new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
}
}
Мое время испытания составляет около 21 секунды (для 300 000 комплектов и 300 000 единиц). Это дает мне около 28 500 операций в секунду (по крайней мере, в 3 раза медленнее, чем я ожидал бы с использованием эталонных тестов). Приложение, которое я конвертирую для использования Redis, довольно чато, и некоторые тяжелые запросы могут приблизиться к 200 000 операций с Redis. Очевидно, я не ожидал ничего подобного в то же время, что и при использовании кеша системы, но задержки после этого изменения значительны. Я что-то не так с моей реализацией, и кто-нибудь знает, почему мои контрольные цифры намного быстрее, чем мои тестовые показатели Stackechange?
Спасибо, Paul
Интересно, почему конвейерная обработка обеспечивает меньшую пропускную способность, чем обработка синхронизации? – Kobynet
@Kobynet справедливый вопрос; возможно, накладные расходы TPL в данном конкретном случае; У меня нет времени прямо сейчас, чтобы разобрать его. –
Спасибо, Марк, это действительно помогло мне! Мне нужно будет реорганизовать это (устаревшее) приложение на многопоточное и асинхронное, чтобы получить максимальную производительность. Я извиняюсь, что это совсем не ясно из кода, который я вставил, но я избегал всякой сериализации в моем тестовом примере. Вы совершенно правы, что я не сравнивался с подобными (используя другую полезную нагрузку, и мой модульный тест не был параллельным), поэтому я полностью понимаю, почему цифры были такими разными. Еще раз спасибо! –