J'ai une base de données Redis sur un serveur Centos, et 3 serveurs Windows y sont connectés avec environ 1 000 lectures/écritures par seconde, tous étant sur le même réseau local, de sorte que le temps de ping est inférieur à une milliseconde. Le problème est qu'au moins 5 % des opérations de lecture sont interrompues, alors que je lis au maximum 3 Ko de données dans une opération de lecture avec 'syncTimeout=15', ce qui est bien plus que la latence du réseau.
J'ai installé Redis sur bash sur mon Windows 10, et simulé le problème. J'ai également arrêté les opérations d'écriture. Cependant, le problème existe toujours avec des délais de 0,5 %, alors qu'il n'y a pas de latence réseau. J'ai également utilisé un serveur Centos sur mon réseau local pour simuler le problème, dans ce cas, j'ai besoin de 100 millisecondes pour 'syncTimeout' afin d'être sûr que le délai d'attente est inférieur à 1 %. J'ai envisagé d'utiliser des dictionnaires pour mettre en cache les données de Redis, de sorte qu'il n'est pas nécessaire de demander chaque élément, et je peux profiter du pipeline. Mais je suis tombé sur StackRedis.L1 qui est développé comme un cache L1 pour Redis, et il n'est pas sûr de la mise à jour du cache L1.
Voici mon code pour simuler le problème :
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);
});
}
et la méthode PerformanceTest est :
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})");
});
}
Je m'attends à ce que toutes les opérations de lecture soient effectuées avec succès en moins de 15 millisecondes. Pour y parvenir, considérer le cache L1 pour un cache Redis est-il une bonne solution ? (C'est très rapide, à l'échelle de la nanoseconde, mais comment faire pour la syncronisation) Ou bien Redis peut être amélioré par un clustering ou autre chose ? (Alors que je l'ai testé en bash sur mon PC, et je n'ai pas reçu le résultat attendu)