C# 提高Redis的性能以减少超时异常

C# 提高Redis的性能以减少超时异常,c#,performance,redis,C#,Performance,Redis,我在Centos服务器上有一个Redis数据库,3台Windows服务器以每秒约1000次的读/写速度连接到该数据库,所有这些都在同一个本地LAN上,因此ping时间不到1毫秒。 问题是至少有5%的读取操作会超时,而我在“syncTimeout=15”的读取操作中读取的数据最大为3KB,这远远超过了网络延迟 我在Windows10的bash上安装了Redis,并模拟了这个问题。我也停止了写操作。但是,0.5%的超时仍然存在问题,同时没有网络延迟。 我还在局域网中使用了Centos服务器来模拟这个

我在Centos服务器上有一个Redis数据库,3台Windows服务器以每秒约1000次的读/写速度连接到该数据库,所有这些都在同一个本地LAN上,因此ping时间不到1毫秒。 问题是至少有5%的读取操作会超时,而我在“syncTimeout=15”的读取操作中读取的数据最大为3KB,这远远超过了网络延迟

我在Windows10的bash上安装了Redis,并模拟了这个问题。我也停止了写操作。但是,0.5%的超时仍然存在问题,同时没有网络延迟。 我还在局域网中使用了Centos服务器来模拟这个问题,在这种情况下,我需要100毫秒的“syncTimeout”来确保超时量小于1%。 我考虑使用一些字典来缓存来自Redis的数据,因此不需要对每个项目进行请求,我可以利用管道。但是我遇到了StackRedis.L1,它是作为Redis的一级缓存开发的,它对更新一级缓存没有信心

这是我模拟问题的代码:

    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);
        });
    }
var connectionMulti=ConnectionMultiplexer.Connect(
“127.0.0.1:6379127.0.0.1:6380,allowAdmin=true,syncTimeout=15”);
//100000把钥匙
var testKeys=File.ReadAllLines(“D:\\RedisTestKeys.txt”);
对于(变量i=0;i<3;i++)
{
var safeI=i;
Task.Factory.StartNew(()=>
{
var serverName=$“服务器{safeI+1}”;
var stringDatabase=connectionMulti.GetDatabase(12);
PerformanceTest($“{serverName}->字符串:”,
key=>stringDatabase.StringGet(key),testkey);
});
}
性能测试方法为:

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})");
        });
    }
private static void PerformanceTest(字符串testName,Func valueExtractor,
IList键)
{
Task.Factory.StartNew(()=>
{
WriteLine($“启动{testName}…”);
var超时=0;
var误差=0;
long totalElapsedMilliseconds=0;
var stopwatch=新秒表();
foreach(var键入键)
{
var redisValue=新的redisValue();
stopwatch.Restart();
尝试
{
redisValue=值提取器(键);
}
捕获(例外e)
{
if(e是TimeoutException)
超时++;
其他的
错误++;
}
最后
{
秒表;
totalElapsedMilliseconds+=秒表。ElapsedMilliseconds;
锁(文件锁)
{
文件.AppendAllLines(“D:\\TestResult.csv”,
新[]
{
$“{stopwatch.ElapsedMilliseconds.ToString()},{redisValue.Length()},{key}”
});
}
}
}
控制台写入线(
$“{testName}{totalElapsedMilliseconds*1.0/keys.Count}(错误:{errors}),(超时:{timeouts})”;
});
}
我预计所有读取操作将在15毫秒内成功完成。 要实现这一点,考虑将一级缓存用于Redis缓存是一个好的解决方案吗?(速度非常快,以纳秒为单位,但如何进行同步) 或者可以通过集群或其他方式增强Redis?(当我在我的电脑上用bash测试时,我没有收到预期的结果)

或者可以通过集群或其他方式增强Redis

Redis可以通过不同的方式进行集群:

  • “常规”redis可以复制到同一台机器或不同机器上的辅助只读节点;然后,您可以向某些复制副本发送“读取”流量
  • redis“cluster”存在,它允许您在多个主节点上分割(shard)键空间,并向每个节点发送适当的请求
  • redis“集群”还可以使用分片节点的只读副本
这是否合适或有用取决于上下文,需要本地知识和测试

要实现这一点,考虑将一级缓存用于Redis缓存是一个好的解决方案吗


是的,这是一个很好的解决方案。你不提出的请求比你提出的请求要快得多(而且对影响的影响要小得多)。有一些工具可以帮助缓存失效,包括使用pub/sub API进行失效。Redis vNext也在研究专门针对这种一级场景的其他知识API。

如果您能分享一个。