StackExchange.Redis Timeout performing 超时问题

StackExchange.Redis Timeout performing 超时问题 最近在做的一个项目,用的.net core 2.1,然后缓存用的Redis,缓存相关封装是同事写的,用的驱动是StackExchange.Redisversion2.0.571,一直听说这个驱动并发情况下有TimeOut bug,项目开发差不多后,我压测了一下,简单的模拟30个用户持续访问某一个有用到缓存的查询接口,结果这么小的压力下超时异常出现: Timeout perform... 阅读详情
AI摘要

本文详细探讨了使用StackExchange.Redis驱动在.NET Core 2.1项目中遇到的Redis超时异常问题。在高并发情况下,30个用户访问带有缓存查询的接口时出现超时异常。作者分析了异常信息,指出问题可能源于线程池工作线程不足,导致Redis的GET操作线程堵塞。解决方案包括更换驱动和调整线程池最小线程数。作者选择了调整线程池设置为200,并提醒该值应根据生产环境适当调整。此外,文章还列举了其他可能导致超时的场景,如数据量过大、同步时间设置不当等,并提供了相应的解决办法。

最近在做的一个项目,用的.net core 2.1,然后缓存用的Redis,缓存相关封装是同事写的,用的驱动是StackExchange.Redis version 2.0.571 ,一直听说这个驱动并发情况下有TimeOut bug,项目开发差不多后,我压测了一下,简单的模拟30个用户持续访问某一个有用到缓存的查询接口,结果这么小的压力下超时异常出现:

Timeout performing GET my_141 (5000ms), inst: 30, qu: 0, qs: 20, in: 20320, serverEndpoint: 172.16.3.119:6379, mgr: 10 of 10 available, clientName: s-119, IOCP: (Busy=0,Free=1000,Min=1,Max=1000), WORKER: (Busy=120,Free=32747,Min=1,Max=32767), v: 2.0.571.20511(Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts))

后面是堆栈信息…

蛋疼了很久,搜了很多文章,得到以下

解决方案

1、换掉,不用这个驱动( 可以看看.net core redis 驱动推荐,为什么不使用 StackExchange.Redis)

2、redis操作修改为全部异步&& ThreadPool.SetMinThreads(200, 200);

我用的第二种解决了问题,主要换驱动也可能遇到坑;还有时间成本问题;

原因简析

我们看到以上的异常信息当中有这么一段:

IOCP: (Busy=0,Free=1000,Min=1,Max=1000),

WORKER: (Busy=120,Free=32747,Min=1,Max=32767),

意思是当前繁忙的WORKER 线程有120个,而系统“要由线程池根据需要创建的新的最小工作程序线程数。”,也就是系统创建的工作线程数不足以满足redis的Get操作的繁忙线程的需求,导致部分Get操作的线程堵塞超时了;

所以我们把“最小线程workerThreads” 修改为200解决问题;

200是我估摸着生产环境服务器设置的,该值设置不合理有可能导致性能问题;


StackExchange.Redis超时的问题

最近公司有个项目,在请求量大的情况下,有大量的错误日志是关于redis超时的问题:

Timeout performing SET XXX, inst: 27, mgr: ProcessReadQueue, err: never, queue: 3, qu: 0, qs: 3, qc: 0, wr: 0, wq: 0, in: 15, ar: 1, clientName: XXX, serverEndpoint: 192.168.x.x:6379, keyHashSlot: 944, IOCP: (Busy=0,Free=1000,Min=4,Max=1000), WORKER: (Busy=4,Free=4091,Min=4,Max=4095) (Please take a look at this article for some common client-side issues that can cause timeouts: http://stackexchange.github.io/StackExchange.Redis/Timeouts)

在网上找解决方案,有说是redis服务端设置的内存不够,客户端连接超时时间设置的长一点,同步时间设置长一点。最后都没有用,只是定位到了是客户端的问题,和服务端没问题。然后继续找在网上发现

StackExchange.Redis是有超时的bug,最后找到csredis解决了问题。把StackExchange.Redis替换掉了。


DevOps StackExchange 连线 Redis 出现 Timeout

同事反应出现大量 Redis 连线 Timeout 的错误,因为 Redis 上存放 Session 跟许多 config cache 资料,如果 Redis 异常会严重影响线上服务,所以立马需要进行除错

首先使用 Redis-cli 确认服务仍正常执行中,接著执行了 Redis Benchmark 检查 server 回应,数据并没有发现异常,使用 Redis Desktop Manager 连线 Redis 资料也可以正常取得,推测 Redis server 本身应该是正常的

接著确认同事的使用情境后发现并非全面性出现 Redis timeout 只有存取几个特定的 key 会出现问题。仔细检查后发现:引起 timeout error 的 key 都有 size 较大的特徵,推测可能是资料量太大造成的

错误讯息

  • 错误讯息
2017-06-28 18:04:56,025 [17] [ERROR] [RedisObjectStore`1] 
Inner exception number - 0
Timeout performing HGETALL faqscache:******.portal.bll.appdatamanager+cachedata, inst: 1, queue: 18, qu: 0, qs: 18, qc: 0, wr: 0, wq: 0, in: 0, ar: 0, clientName: TestAPP01, serverEndpoint: 127.0.0.1:8188, keyHashSlot: 3414, IOCP: (Busy=0,Free=1000,Min=2,Max=1000), WORKER: (Busy=6,Free=8185,Min=2,Max=8191) (Please take a look at this article for some common client-side issues that can cause timeouts: http://stackexchange.github.io/StackExchange.Redis/Timeouts)
    at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)
    at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)
    at StackExchange.Redis.RedisDatabase.HashGetAll(RedisKey key, CommandFlags flags)
    at ******.Portal.BLL.Redis.RedisObjectStore`1.Get(String key)
Main exception & its inner exception Log end

解决方式

修改资料同步 timeout 设定 - 放宽 syncTimeout 时间 (预设 1000 毫秒)

  1. 原始 redis 连线资讯
public static class RedisConnectionFactory
{
    
    private static readonly Lazy<ConnectionMultiplexer> Connection;
    public static IServer RedisServer;
        
    static RedisConnectionFactory()
    {
        var connectionString = "127.0.0.1:6379,127.0.0.1:6380,password=password";
        var options = ConfigurationOptions.Parse(connectionString);
        Connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(options));
        RedisServer = GetConnection.GetServer(options.EndPoints.First());
    }
    public static ConnectionMultiplexer GetConnection => Connection.Value;
    public static IDatabase RedisDB => GetConnection.GetDatabase();
}
  1. 修改后
public static class RedisConnectionFactory
{
    private static readonly Lazy<ConnectionMultiplexer> Connection;
    public static IServer RedisServer;
    static RedisConnectionFactory()
    {
        var connectionString = "127.0.0.1:6379,127.0.0.1:6380,password=password,syncTimeout =3000";
        var options = ConfigurationOptions.Parse(connectionString);
        Connection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(options));
        RedisServer = GetConnection.GetServer(options.EndPoints.First());
    }
    public static ConnectionMultiplexer GetConnection => Connection.Value;
    public static IDatabase RedisDB => GetConnection.GetDatabase();
}

心得

放宽资料同步时间后,timeout 问题确实获得解决,但还是建议同事从源头端来缩小 redis 的资料量大小,一来减少 network 传输的 io ,二来可以增加 redis 回应速度


StackExchange.Redis性能调优

大家经常出现同步调用Redis超时的问题,但改成异步之后发现错误非常少了,但却可能通过前后记日志之类的发现Redis命令非常慢。

PS: 以后代码都在Windows bash中运行,StackExchange.Redis版本为1.2.6

先快速重现问题和解决问题,大家先运行下面的代码

public static async Task Main(string[] args)
{
    ThreadPool.SetMinThreads(8, 8);
    using (var connection = await ConnectionMultiplexer.ConnectAsync("localhost"))
    {
        connection.PreserveAsyncOrder = false;

        var db = connection.GetDatabase(0);
        var sw = Stopwatch.StartNew();

        await Task.WhenAll(Enumerable.Range(0, 10)
            .Select(_ => Task.Run(() =>
            {
                db.StringGet("aaa");

                Thread.Sleep(1000);
            })));

        Console.WriteLine(sw.ElapsedMilliseconds);
    }
}

运行发现抛出StackExchange.Redis.RedisTimeoutException,为什么呢?是因为当前工作线程根本不够用,同步等待时已经超时。具体请看源代码

如果将上面的ThreadPool.SetMinThreads(8, 8)改成ThreadPool.SetMinThreads(100, 100)呢?是不是不抛异常了呢。

再说异步接口变慢的问题,大家先运行下面的代码:

public static async Task Main(string[] args)
{
    var tcs = new TaskCompletionSource<bool>();
    var sw = Stopwatch.StartNew();

    Console.WriteLine($"Main1: {sw.ElapsedMilliseconds}, ThreadId: {Environment.CurrentManagedThreadId}");

    var task = Task.Run(() =>
    {
        Thread.Sleep(10);
        Console.WriteLine($"Run1: {sw.ElapsedMilliseconds}, ThreadId: {Environment.CurrentManagedThreadId}");
        tcs.TrySetResult(true);
        Console.WriteLine($"Run2: {sw.ElapsedMilliseconds}, ThreadId: {Environment.CurrentManagedThreadId}");
        Thread.Sleep(10000);
    });

    var a = tcs.Task.ContinueWith(_ => { Console.WriteLine($"a: {sw.ElapsedMilliseconds}, ThreadId: {Environment.CurrentManagedThreadId}"); });
    var b = tcs.Task.ContinueWith(_ => { Console.WriteLine($"b: {sw.ElapsedMilliseconds}, ThreadId: {Environment.CurrentManagedThreadId}"); });
    var c = tcs.Task.ContinueWith(_ => { Console.WriteLine($"c: {sw.ElapsedMilliseconds}, ThreadId: {Environment.CurrentManagedThreadId}"); });

    await tcs.Task;
    Console.WriteLine($"Main2: {sw.ElapsedMilliseconds}, ThreadId: {Environment.CurrentManagedThreadId}");
    Thread.Sleep(100);
    await Task.Delay(10);
    Console.WriteLine($"Main3: {sw.ElapsedMilliseconds}, ThreadId: {Environment.CurrentManagedThreadId}");
}

最终输出结果发现Run1和Main2是使用相同的线程吧,而Run2的ElapsedMilliseconds基本上就是在Run1的基础上加100。

然后再回到调用Redis代码上

static async Task Main(string[] args)
{
   ThreadPool.SetMinThreads(100, 100);
    using (var connection = await ConnectionMultiplexer.ConnectAsync("localhost"))
    {
        var db = connection.GetDatabase(0);
        var sw = Stopwatch.StartNew();

        await Task.WhenAll(Enumerable.Range(0, 10)
            .Select(_ => Task.Run(async () =>
            {
                await db.StringGetAsync("aaa");

                Thread.Sleep(100);
            })));

        Console.WriteLine(sw.ElapsedMilliseconds);
    }
}

你们发现输出是100多还是1000多?为什么?原来是因为sdk中有一个特殊的设置,要保护异步代码执行的顺序,然后我们在GetDatabase行之前加一个代码connection.PreserveAsyncOrder = false;

然后再运行一次看看结果是多少呢?通过上面再做代码基本上可以确定异步慢是和TaskCompletionSource和关系的,具体请看sdk的源代码。

总结上面两点,简单得通过SetMinThreads和connection.PreserveAsyncOrder = false可以解决绝大部分问题,但更多其他深层次的问题怎么发现呢?

下面就要介绍StackExchange.Redis两个神器ConnectionCounters和IProfiler

  1. 通过connection.GetCounters().Interactive获得的对象之后其中有三个属性非常有用
public class ConnectionCounters
{
    /// <summary>
    /// Operations that have been requested, but which have not yet been sent to the server
    /// </summary>
    public int PendingUnsentItems { get; }

    /// <summary>
    /// Operations that have been sent to the server, but which are awaiting a response
    /// </summary>
    public int SentItemsAwaitingResponse { get; }

    /// <summary>
    /// Operations for which the response has been processed, but which are awaiting asynchronous completion
    /// </summary>
    public int ResponsesAwaitingAsyncCompletion { get; }
}
  1. 每个属性表示当前redis连接的待完成的命令当前所处的状态。通过字面意思就可以知道PendingUnsentItems表示已经进行待发送队列还未发送出去的命令;SentItemsAwaitingResponse表示已经发送出去但还没有收到响应结果的命令;ResponsesAwaitingAsyncCompletion则表示已经收到响应的命令,但还没有调用TaskCompletionSource<T>().TrySetResult()的命令。
    其中PendingUnsentItems和SentItemsAwaitingResponse过大的原因基本上是因为网络阻塞了,你需要检查一下网络带宽或者redis的value是否很大。
    ResponsesAwaitingAsyncCompletion则是因为await之后的代码,如上面示例中的代码,线程占用了很长的同步时间,需要优化代码和将PreserveAsyncOrder设置为false。

  2. ConnectionCounters分析的是一个线程的瞬时状态,而IProfiler则可以跟踪一个请求总共执行了多少的redis命令以及他们分别使用了多长时间,具体细节请大家写代码体验。参考文档

发现问题就需要解决问题,也就需要深层次得去学习才能解决问题。我不喜欢写文章,但发现最近有好几篇说redis超时的问题,最终我还是想把自己的踩坑的心得分享给大家。

这在里说一个好消息,那就是StackExchange.Redis 2.0已经从重构了异步队列,使用管道方式解决异步慢的问题


StackExchange.Redis 之 操作Redis链接字符串配置(链接Redis集群)

Redis链接字符串可以提出来放到 Config文件当中:

  <connectionStrings>
    <add name="Connection_Redis" connectionString="127.0.0.1:6379,127.0.0.1:6380,127.0.0.1:6381,127.0.0.1:6382,password=123456,abortConnect=false" />
  </connectionStrings>

当有多个Redis实例时,可以设置链接多个实例,中间用逗号分隔即可(比如:使用Redis集群)。

public class RedisCacheHelper
    {
        private readonly Logger _log = LogManager.GetCurrentClassLogger();

        /// <summary>
        /// 连接字符串
        /// </summary>
        private static string _connectionString;

        /// <summary>
        /// redis 连接对象
        /// </summary>
        private static IConnectionMultiplexer _connMultiplexer;

        /// <summary>
        /// 实例化对象
        /// </summary>
        private static RedisCacheHelper _cacheHelper;
        /// <summary>
        /// 实例
        /// </summary>
        private static RedisCacheHelper _instance;

        /// <summary>
        /// 锁
        /// </summary>
        private static readonly object Locker = new object();

        /// <summary>
        /// 数据库
        /// </summary>
        private IDatabase _db;


        /// <summary>
        /// 默认链接实例
        /// </summary>
        private RedisCacheHelper()
        {
            _connectionString = ConfigurationManager.ConnectionStrings["Connection_Redis"].ConnectionString;
            _connMultiplexer = ConnectionMultiplexer.Connect(_connectionString);
            //添加注册事件
            AddRegisterEvent();
        }

        /// <summary>
        /// 获取 Redis 连接对象
        /// </summary>
        private IConnectionMultiplexer Connnection
        {
            get
            {
                if (_connMultiplexer == null || !_connMultiplexer.IsConnected)
                {
                    lock (Locker)
                    {
                        if (_connMultiplexer == null || !_connMultiplexer.IsConnected)
                        {
                            _connMultiplexer = ConnectionMultiplexer.Connect(_connectionString);
                        }
                    }
                }
                return _connMultiplexer;
            }
        }

        /// <summary>
        /// 获取指定db,默认不指定
        /// </summary>
        /// <param name="db"></param>
        /// <returns></returns>
        private IDatabase GetDatabase(int db = -1)
        {
            return Connnection.GetDatabase(db);
        }

        /// <summary>
        /// 调用实例,通过该实例调用Redis
        /// </summary>
        public static RedisCacheHelper Instance
        {
            get
            {
                if (_cacheHelper != null) return _cacheHelper;
                lock (Locker)
                {
                    if (_cacheHelper != null) return _cacheHelper;
                    _cacheHelper = new RedisCacheHelper();
                }
                return _cacheHelper;
            }
        }

        #region 注册事件

        /// <summary>
        /// 添加注册事件
        /// </summary>
        private void AddRegisterEvent()
        {
            _connMultiplexer.ConnectionRestored += ConnMultiplexer_ConnectionRestored;
            _connMultiplexer.ConnectionFailed += ConnMultiplexer_ConnectionFailed;
            _connMultiplexer.ErrorMessage += ConnMultiplexer_ErrorMessage;
            _connMultiplexer.ConfigurationChanged += ConnMultiplexer_ConfigurationChanged;
            _connMultiplexer.HashSlotMoved += ConnMultiplexer_HashSlotMoved;
            _connMultiplexer.InternalError += ConnMultiplexer_InternalError;
            _connMultiplexer.ConfigurationChangedBroadcast += ConnMultiplexer_ConfigurationChangedBroadcast;
        }

        /// <summary>
        /// 重新配置广播时(通常意味着主从同步更改)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ConnMultiplexer_ConfigurationChangedBroadcast(object sender, EndPointEventArgs e)
        {
            _log.Info($"{nameof(ConnMultiplexer_ConfigurationChangedBroadcast)}: {e.EndPoint}");
        }

        /// <summary>
        /// 发生内部错误时(主要用于调试)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ConnMultiplexer_InternalError(object sender, InternalErrorEventArgs e)
        {
            _log.Error($"{nameof(ConnMultiplexer_InternalError)}: {e.Exception}");
        }

        /// <summary>
        /// 更改集群时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ConnMultiplexer_HashSlotMoved(object sender, HashSlotMovedEventArgs e)
        {
            _log.Info(
                $"{nameof(ConnMultiplexer_HashSlotMoved)}: {nameof(e.OldEndPoint)}-{e.OldEndPoint} To {nameof(e.NewEndPoint)}-{e.NewEndPoint}");
        }

        /// <summary>
        /// 配置更改时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ConnMultiplexer_ConfigurationChanged(object sender, EndPointEventArgs e)
        {
            _log.Info($"{nameof(ConnMultiplexer_ConfigurationChanged)}: {e.EndPoint}");
        }

        /// <summary>
        /// 发生错误时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ConnMultiplexer_ErrorMessage(object sender, RedisErrorEventArgs e)
        {
            _log.Error($"{nameof(ConnMultiplexer_ErrorMessage)}: {e.Message}");
        }

        /// <summary>
        /// 物理连接失败时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ConnMultiplexer_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
        {
            _log.Fatal($"{nameof(ConnMultiplexer_ConnectionFailed)}: {e.Exception}");
        }

        /// <summary>
        /// 建立物理连接时
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ConnMultiplexer_ConnectionRestored(object sender, ConnectionFailedEventArgs e)
        {
            _log.Info($"{nameof(ConnMultiplexer_ConnectionRestored)}: {e.Exception}");
        }

        #endregion
    }

以上Redis链接就配置好了,使用方式如下:首先在把集群中的主从服务都开启,3主、3从
在这里插入图片描述
然后在代码中进行操作验证,向缓存中插入一条数据,然后循环读写数据,循环的时候手动任意关闭Redis服务当中的 1~2个 服务器

while (true)
            {
                //设置age
                RedisCacheHelper.Instance.Set("age", "10", new TimeSpan(0, 5, 0));

                //获取age
                var getage = RedisCacheHelper.Instance.Get("age");
                Console.WriteLine(DateTime.Now.ToString("HH:mm:ss.fff") + ":" + getage);

                Thread.Sleep(1000); // 等待1s
            }

成功将缓存存入到服务器当中,运行效果如下:
在这里插入图片描述

此时查看Redis集群,发现主从实例都有数据了,接下来我们把其中任意1个 Redis实例关掉 (上边运行的循环代码程序不要关闭)
在这里插入图片描述
发现程序正常运行:
在这里插入图片描述
但是上边的步骤,我经过多次测试,在任意关闭某个实例的时候,偶尔会报如下错误:集群挂了
在这里插入图片描述
我们把写的方法注释掉,只保留读取的代码,同样会偶尔报异常。
在这里插入图片描述
但是大部分情况下,关掉其中一个实例,程序都正常运行:
在这里插入图片描述
在这里插入图片描述


使用StackExchange.Redis客户端进行Redis访问出现的Timeout异常排查

问题产生

这两天业务系统在redis的使用过程中,当并行客户端数量达到200+之后,产生了大量timeout异常,典型的异常信息如下:

Timeout performing HVALS Parser2#Hash#VersionState, inst: 1, mgr: ExecuteSelect, err: never, queue: 2, qu: 0, qs: 2, qc: 0, wr: 0, wq:> 0, in: 0, ar: 0, clientName: GS-SERVER-2894, IOCP: (Busy=0,Free=1000,Min=8,Max=1000), WORKER: (Busy=0,Free=32767,Min=8,Max=32767), Local-CPU: 0% (Please take a look> at this article for some common client-side issues that can cause timeouts: https://github.com/StackExchange/StackExchange.Redis/tree/master/Docs/Timeouts.md)

No connection is available to service this operation: HVALS Parser2#Hash#VersionState

SocketFailure on HVALS

运行环境:

Redis服务器版本:2.8.19
.net Framework版本:4.5.2
StackExchange.Redis版本:1.1.603

问题分析

首先定位问题,排除Redis基础组件本身问题,使用redis提供的benchmark工具进行测试:

redis-benchmark -h 10.200.XX.XX -p 30301 -q -n 100000 -c 300 -d 10240

由于redis使用docker提供服务因此端口映射到30301,模拟100000次真实场景请求,300并发,每次请求数据大小10K。

经测试,对常见的hset,hget,sadd,spop等短耗时操作,TPS均保持在25K-30K之间,因此初步排除docker提供的redis服务的问题。

因此问题大致定位在了业务系统代码中,即使用的redis客户端工具(StackExchange.Redis)这部分。

通过StackExchange对Timeout异常的相关信息(可见这个问题挺常见)及stackoverflow等站点上的相关内容,产生timeout异常比较常见的原因包含(但不限于):

1:服务器资源不足;

2:耗时过长的指令(StackExchange客户端连接的只读属性TimeoutMilliseconds=1000);

3:StackExchange阻塞任务过多(异常信息中的qs值持续增长),对这种情况,StackExchange给出的建议是实现一个复用器池(ConnectionMultiplexer Pool)并动态选取最低负载的复用器进行连接,避免一个链接timeout导致所有链接阻塞的情况;

4:CLR中Thread Pool最小按需创建线程数过小导致的等待成本(500ms),可见StackExchange的ConnectionMultiplexer使用的是线程池;

此外,在StackExchange.Redis项目的Issue中与Time out相关的主题中,也有人提及在更新StackExchange.Redis的客户端版本后(1.1.605+)该异常不再出现的问题。

问题解决

根据以上可能产生问题的原因,对业务代码做出以下修改:

1:不再继续使用StackExchange.Redis内部封装的主/从线程池,明确主/从ConnectionMultiplexer对象;

2:修改CLR的Thread Pool最小创建线程阈值数量;

3:在ConnectionMultiplexer单例视线中加入对其IsConnected属性的判断,在其连接断开后手动释放资源并重新连接;

4:避免如HVALS等可能导致慢操作的指令;

5:升级StackExchange.Redis版本至1.1.605+(目前最新版本1.1.608)。

修改完毕后进行测试,time out异常目前已排除。

StackExchange.Redis客户端(V1.1.608)经测试有这么一个特质,即,由complexer单例对象创建的IDatabase对象,在产生Timeout异常后会导致这个complexer单例对象超时,即由其创建的新的IDatabase对象也会继续Timeout,相当蛋疼。。。

实际使用过程中,由于网络各种原因,出现Timeout异常难免,但是无法恢复确实很麻烦。测试complexer对象无法dispose,close后重建。。

【Azure Redis 缓存】使用StackExchange.Redis,偶发ERROR - Timeout performing HSET (15000ms) 在第一个错误中,可以发现 WORKER 的Busy 数量 远大于 Min 数量 WORKER: (Busy=17,Free=8174,Min=2,Max=8191),,所以可以通过设置Worker/IOCP的线程数来解决这个问题。使用StackExchange.Redis 作为Redis客户端SDK,连接Azure Redis服务,长期运行后发现,每天都偶发 Timeout Error。当在复杂的环境中面临问题,格物之道需:浊而静之徐清,安以动之徐生。**1)查看慢指令(slowlogs) : ** 阅读详情

相关推荐

C#与Redis集成实战:从StackExchange.Redis选型到生产级应用

缓存是提升应用性能、降低数据库负载的核心技术手段,通过在内存中存储热点数据,实现数据的快速访问。其原理基于局部性原理,将频繁访问的数据置于高速存储介质中。在分布式系统中,缓存的技术价值尤为突出,能够有效应对高并发场景,提升系统吞吐量和响应速度。Redis作为高性能的内存数据存储,凭借其丰富的数据结构和持久化能力,成为实现分布式缓存的主流选择。在C#开发领域,StackExchange.Redis客户端库因其高性能的多路复用连接、线程安全设计和完整的Redis命令映射,成为连接C#应用与Redis服务的事实标

Hi, Sun 373

StackExchange.Redis获取数据超时解决方案

StackExchange.Redis 加载大批量hash数据超时报错: StackExchange.Redis.RedisTimeoutException: Timeout performing HGET Cache.IncomeShare.AccountData@Cache.IncomeShare.AccountData.InnerIncomeDistributionItem, inst: 1, mgr: ExecuteSelect, err: never, queue: 2, qu: 0, qs: 2

冻死的企鹅 2329

【实战】Windows 10 下利用CodeSoft 6 ActiveX组件实现.NET条形码标签自动化打印

本文详细介绍了在Windows 10环境下使用CodeSoft 6 ActiveX组件实现.NET条形码标签自动化打印的实战经验。从开发环境搭建、COM引用配置到模板设计与变量绑定,提供了完整的解决方案和优化技巧,帮助开发者高效完成标签打印任务。

weixin_30666401的博客 262

好烦,一封报警邮件,大量服务节点 redis 响应超时,又要加班了

因实际应用中出现经常 Redis 超时问题,StackExchange.Redis 在 Github 上 Timeouts 一文从多个方面进行分析,并提供相应的解决方案, 为方便日后再次出现该问题时快速查阅,特写下本文作为技术笔记,同时给英文不太好的程序员(媛)提供参考。 对于使用过 StackExchange.Redis 的程序员(媛),经常碰到类似于以下的异常: Timeout performing GET keyName, inst: 1, mgr: ExecuteSelect, err: .

Java架构师联盟 1563

.net core 下使用StackExchange的Redis库访问超时解决

目录问题:并发稍微多的情况下Redis偶尔返回超时给出了参考网址?结论小备注引用链接 问题:并发稍微多的情况下Redis偶尔返回超时 StackExchange的Redis类库,用的较多,但偶尔报的问题非常让人迷惑,访问超时,队列XXX… 问题出在Redis服务器吗?可是其他应用访问都正常啊,难道要把这个类库替换掉? 问题描述如下: Timeout performing GET keyName, ...

网尘的技术专栏 8156

小白跑WRF第三天,安装三方依赖库

小白跑WRF第三天,安装三方依赖库各类安装包的准备 各类安装包的准备 官网教程:https://www2.mmm.ucar.edu/wrf/OnLineTutorial/compilation_tutorial.php 根据官网教程需要的安装包有以下几个 系统环境 用途 zlib-1.2.7 zlib是提供数据压缩用的函式库。 netcdf-4.1.3 读nc文件的。 mpich-3.0.4 用于并行运算的工具。 libpng-1.2.50 libpng是一款C语言编写的比较底层

weixin_42372313的博客 1万+

StackExchange.Redis .net core Timeout performing 超时问题

最近在做的一个项目,用的.net core 2.1,然后缓存用的Redis,缓存相关封装是同事写的,用的驱动是StackExchange.Redis version 2.0.571 ,一直听说这个驱动并发情况下有TimeOut bug,项目开发差不多后,我压测了一下,简单的模拟30个用户持续访问某一个有用到缓存的查询接口,结果这么小的压力下超时异常出现: Timeout performing GE...

weixin_30347009的博客 1072

攻克TypeError: Cannot read properties of undefined (reading ‘NormalModule‘)的四种实战策略

本文详细解析了`TypeError: Cannot read properties of undefined (reading 'NormalModule')`错误的四种实战解决策略。从版本一致性检查、包管理器优化到依赖替换和构建环境配置,帮助开发者快速定位和解决Webpack构建过程中的常见问题,提升开发效率。

weixin_42523670的博客 242

从 Redis 客户端超时到 .NET 线程池挑战

摘要: 本文探讨了.NET应用中使用StackExchange.Redis时常见的超时问题及其解决方案。超时多由客户端线程池管理不当引发,如线程饥饿、线程窃取和线程池阻塞。在高并发环境下,如ASP.NET Core服务中,这些问题尤为突出。通过分析线程池动态调整机制及StackExchange.Redis的依赖关系,提出了优化策略,包括调整线程池配置、启用防窃取标志、使用连接池和异步化操作。实际案例表明,这些优化可显著降低超时率,提升系统稳定性。

xdpcxq的专栏 787

基于 openEuler 24.03 LTS 源码编译安装 Zabbix 7.4

Zabbix是一款开源的企业级分布式监控系统,支持网络、服务器、应用等多种IT资源的监控。核心功能包括数据采集、告警通知、可视化展示等,采用Server/Agent架构,支持多种操作系统。本文详细介绍了在openEuler 24.03系统上部署Zabbix 7.4.2的完整流程,包括环境准备、MySQL配置、PHP/Apache安装、Zabbix编译安装等步骤,为构建企业级监控系统提供了实践指导。

广然笔记 1188

从VoLTE高清通话到5G新通话:手把手带你用Wireshark抓包分析QCI 1, 2, 5, 9的建立与切换过程

本文详细解析了从VoLTE高清通话到5G新通话的QCI(QoS Class Identifier)建立与切换过程,通过Wireshark抓包实战演示如何分析QCI 1、2、5、9的承载机制。内容涵盖QCI基础概念、实验环境搭建、VoLTE通话建立过程分析以及5G新通话中的QoS演进,为网络工程师和通信技术爱好者提供实用的技术指南和优化建议。

weixin_30788619的博客 342

StackExchange.Redis.RedisTimeoutException: Timeout performing GET xxx, inst: 1

.Net Core 2.0连接Redis 后读取值报错Timeout 问题比较简单,解决方案也比较简单,这个错误的出现情况是在多人同时访问服务器然后连接redis读取的时候出现的也不是必现,是有一定几率出现,当然还有一个前提你首先得以单例模式注入redis操作服务,如果你还不是单例模式注入的话先回去改改试试看, 出现这个错误的解决方案:将操作改成异步即可。如:异步读取 ...

koloumi的博客 5888

iOS马甲包过审实战:如何用5天时间搞定4.3审核(附完整代码混淆方案)

本文提供了一套为期五天的高效实战方案,专门解决iOS应用因重复或抄袭问题而被App Store的4.3条款拒绝的难题。方案涵盖深度分析、代码混淆、资源翻新及环境隔离等系统性步骤,并附有完整的代码混淆示例,旨在帮助开发者在合规框架内重塑应用,显著提升过审成功率。

weixin_29234239的博客 145

导致Redis超时(Timeouts)常见问题

因实际应用中出现经常 Redis 超时问题,StackExchange Redis 在 Github 上 Timeouts 一文从多个方面进行分析,并提供相应的解决方案, 因实际应用中出现经常 Redis 超时问题,StackExchange.Redis 在 Github 上 Timeouts 一文从多个方面进行分析,并提供相应的解决方案, 为方便日后再次出现该问题时快速查阅,特写下本文作为技术...

黎林果的专栏 6万+

从战略到执行:业务领先模型 BLM 的第一把钥匙「差距分析」

业务领先模型「BLM」(Business Leadership Model),俗称“别乱摸”,起源于哈佛商学院的战略理论研究,是一套完整的战略规划方法论。 后来被 IBM 发扬光大,IBM 在转型关键时期完成了对 BLM 模型的导入和创新,从此这个模型成为 IBM 中高层用于战略制定与执行联接的方法与平台。 再到后来华为花巨资引入了 BLM 模型,经过多年的应用,将其演化成了公司战略规划和落地的主要方法与流程,也因此被中国科技企业所认识和接受。 BLM 模型可以解决哪些问题? 在企业内,

产品线负责人 2400

Codex 100个真实案例 - 用AI批量清洗Excel脏数据(10万行3分钟搞定)

每个做数据分析的人都被"脏数据"折磨过——空值、重复行、日期格式五花八门、手机号多一位少一位……手动清洗几千行就已经让人崩溃,更别提10万行了。本文将展示如何用 Codex 生成一套完整的 Python pandas 数据清洗工具,从读取Excel/CSV、识别脏数据、自动清洗、生成清洗报告,到可视化对比清洗前后的数据质量,全程自然语言驱动,10万行数据3分钟搞定!

yueyeguzhuo的专栏 86

redis使用sysc超时_与同步请求,并仅在异步方法异步请求的响应速度慢的Redis缓存越来越超时...

First of all I am using Azure Redis Cache service and StackExchange.Redis(1.0.371) client with my MVC 5 and Web Api 2 app. I am getting very interesting behaviors. getting timeout with sync requests a...

weixin_28698129的博客 437

pandas教程:2012 Federal Election Commission Database 2012联邦选举委员会数据库

里面包含了支持者的名字,职业和雇主,地址,赞助金额。我们可以已经能想到如何切割、整理数据,来提取赞助者的统计数据,或提取宣传活动的模式,这里我们展示一些不同的分析方法。可以看到有些职业是同一种工作类型,指代的是同一个东西。这两个连续操作是分别独立执行的,一个结束后,另一个才开始。上,这里我是把数据集压缩成了ZIP格式,解压后能正常导入)。我觉得也有必要好好了解一下,这个网站做了很好的讲解,),所以我们最好添加这样的信息。这样的情况,即把两个索引操作连在一起。,发现映射关系被正常执行了,所以这里的。

Cachel Wood的博客 349

从 Redis 客户端超时到 .NET 线程池挑战:饥饿、窃取与阻塞的全景解析

通过多次排查和优化,我发现这些问题的根源大多指向 .NET 的线程池(ThreadPool)管理机制,包括线程饥饿(thread starvation)、线程窃取(thread theft)和线程池阻塞等现象。本文将从 StackExchange.Redis 的超时问题入手,逐步深入探讨这些线程池相关的挑战,提供详细的分析、代码示例和优化建议。在我的项目中,一个典型的场景是:在高并发请求下,应用突然出现批量超时。进一步检查日志,发现线程池的忙碌线程数激增,这让我意识到需要深入了解 .NET 的线程池管理。

farway000的博客 70

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Azure Redis 缓存使用注意事项与排查问题文档整理

StackExchange.Redis 使用名为synctimeout的配置设置进行同步操作,该设置的默认值为 1000 毫秒。如果同步调用未在规定时间内完成,StackExchange.Redis 客户端会引发类似于以下示例的超时错误。 System.TimeoutException: Timeout performing MGET 2728cc84-58ae-406b-8ec8-3f9...

weixin_30599769的博客 185

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

redis各类错误可能的解决方案

1.报Timeout performing EVAL 这个可能是连到读库从库了,直接改成写库就没问题了。 2. 各种ConnectTimeout 一般是偶尔或经常就超时,这种情况,找了各种回答,最后在stackoverflow上看到一个大佬给了个解决方法,试了下,可以了。 对应地址:https://stackoverflow.com/questions/2316...

weixin_30892987的博客 1064

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Are you seeing high number of busyio or busyworker threads in the timeout exception?

StackExchange.Redis Are you getting network or CPU bound? Verify what’s the maximum bandwidth supported on your client and on the server where redis-server is hosted. If there are requests that...

weixin_30306905的博客 346

公司项目redis 项目报错 记事

异常内容: TimeoutperformingGETKey_CacheHSCode,inst:1,mgr:ExecuteSelect,err:never,queue:2,qu:0,qs:2,qc:0,wr:0,wq:0,in:0,ar:0,clientName:WIN-SC991PA4UMG,IOCP:(Busy=0,Free=1000...

weixin_30800807的博客 427
上一篇: .NetFramework升级.Net5 各种第三方升级记录
下一篇: Abp vNext 关于引用swagger注释补充
.NET跨平台
博客等级 码龄15年 6066粉丝 738原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值