У меня есть база данных Redis на сервере Centos, и к ней подключено 3 сервера Windows со скоростью примерно 1000 операций чтения / записи в секунду, причем все они находятся в одной локальной сети, поэтому время пинга составляет менее одной миллисекунды. Проблема в том, что по крайней мере 5 процентов операций чтения уходит в тайм-аут, в то время как я читаю максимум 3 КБ данных в операции чтения с 'syncTimeout = 15', что намного больше, чем задержка в сети.
Я установил Redis на bashна моей windows 10 и смоделировать проблему. Я также прекратил писать операции. Однако проблема все еще существует с 0,5-процентным таймаутом, в то время как нет задержки в сети. Я также использовал Centos Server в своей локальной сети для имитации проблемы, в этом случае мне нужно 100 миллисекунд для syncTimeout, чтобы убедиться, что время ожидания составляет менее 1 процента. Я подумал об использовании некоторых словарей для кэширования данных из Redis, поэтому нет необходимости запрашивать каждый элемент, и я могу воспользоваться конвейером. Но я наткнулся на StackRedis.L1, который разработан как кэш L1 для Redis, и он не уверен в обновлении кеша L1.
Это мой код для симуляции проблемы:
var connectionMulti = ConnectionMultiplexer.Connect(
"127.0.0.1:6379,127.0.0.1:6380,allowAdmin=true,syncTimeout=15");
// 100,000 keys
var testKeys = File.ReadAllLines("D:\\RedisTestKeys.txt");
for (var i = 0; i < 3; i++)
{
var safeI = i;
Task.Factory.StartNew(() =>
{
var serverName = $"server {safeI + 1}";
var stringDatabase = connectionMulti.GetDatabase(12);
PerformanceTest($"{serverName} -> String: ",
key => stringDatabase.StringGet(key), testKeys);
});
}
и метод PerformanceTest:
private static void PerformanceTest(string testName, Func<string, RedisValue> valueExtractor,
IList<string> keys)
{
Task.Factory.StartNew(() =>
{
Console.WriteLine($"Starting {testName} ...");
var timeouts = 0;
var errors = 0;
long totalElapsedMilliseconds = 0;
var stopwatch = new Stopwatch();
foreach (var key in keys)
{
var redisValue = new RedisValue();
stopwatch.Restart();
try
{
redisValue = valueExtractor(key);
}
catch (Exception e)
{
if (e is TimeoutException)
timeouts++;
else
errors++;
}
finally
{
stopwatch.Stop();
totalElapsedMilliseconds += stopwatch.ElapsedMilliseconds;
lock (FileLocker)
{
File.AppendAllLines("D:\\TestResult.csv",
new[]
{
$"{stopwatch.ElapsedMilliseconds.ToString()},{redisValue.Length()},{key}"
});
}
}
}
Console.WriteLine(
$"{testName} {totalElapsedMilliseconds * 1.0 / keys.Count} (errors: {errors}), (timeouts: {timeouts})");
});
}
Я ожидаю, что все операции чтения будут успешно выполнены менее чем за 15 миллисекунд. Достижение этого, является ли кэш L1 для кэша Redis хорошим решением? (Это очень быстро, в масштабе наносекунды, но как я могу сделать для синхронизации) Или Redis может быть улучшен путем кластеризации или что-то еще? (Пока я тестировал его на bash на моем ПК, и я не получил ожидаемый результат)