首页 > 解决方案 > 在 WPF 应用程序中使用 StackExchange.Redis 的正确方法

问题描述

我在我的应用程序中实现了 Stackexchange.Redis 以从 redis 数据库列表中获取数据。在登录应用程序(WPF)时创建一个列表并推送由另一个模块(C++)通过创建 redis db 的服务器获取的数据。服务器模块将响应推送到用户特定列表,WPF 模块通过每 10 毫秒轮询一次从该列表中读取数据。

我创建了以下方法来执行这些任务。

  1. 构造函数
      public RedisConnection()
                {
                    try
                    {
                        ConnectionMultiplexer.SetFeatureFlag("preventthreadtheft", true);
                        if (_databaseRedis != null)
                            this.DatabaseRedis = _databaseRedis;
                        if (_clientSubscriptionChannnel != null)
                            this.ClientSubscriptionChannnel = _clientSubscriptionChannnel;
                    }
                    catch (Exception ex)
                    {
                    }
                }
  1. 连接 Redis
       public bool CreateConnection(Hashtable ParamsHt)
        {          
            try
            {
                var settings = ConfigurationOptions.Parse(ParamsHt["RedisIP"].ToString());
                settings.ConnectRetry = 3;
                settings.ConnectTimeout = 10000;
                settings.SyncTimeout = 20000;
                connection = ConnectionMultiplexer.Connect(settings);
                if (connection.IsConnected)
                {
                    DatabaseRedis = connection.GetDatabase();
                }
                return isConnected = connection.IsConnected;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
  1. 从列表中获取数据
       private  void FetchListToProcess()
        {
            try
            {                
                IDatabase database = connection.GetDatabase();                 
                long length = database.ListLength(ConfigurationService.ListToInsertRequest + "_" + LoginID);
                if (length > 0)
                {
                    RedisValue rv = database.ListLeftPop(ConfigurationService.ListToInsertRequest+"_"+ LoginID, CommandFlags.None);
                    if (rv.HasValue)
                    {
                        database.ListRemove(LoginID, rv);
                        byte[] userObject = (byte[])rv;
                        CommonOM.MessageHeader HeaderObj = CommonBL.ByteArrayToStructure<CommonOM.MessageHeader>(userObject);
                        int MessageType = HeaderObj.messageCode;
                        if (MessageType == Convert.ToInt32(TRANSACTION_REQUEST_CODE.HEART_BEAT))
                        {   
                           delRecieveReadyRedisHearbeat delHeartbeatReciever = new delRecieveReadyRedisHearbeat(_heartbeatHelper.OnRecieveHeartbeat);
                           delHeartbeatReciever.BeginInvoke(MessageType, userObject, null, null);
                           
                        }
                        else 
                        {    
                           delRecieveReadyRedisHearbeat delHeartbeatReciever = new delRecieveReadyRedisHearbeat(_heartbeatHelper.OnRecieveHeartbeat);
                           delHeartbeatReciever.BeginInvoke(MessageType, userObject, null, null);
                          
                        }
                        else
                        {
                            delRecieveReadyRedisMessages delReady = new delRecieveReadyRedisMessages(_connectionHelper.OnReceive);
                            delReady.BeginInvoke(MessageType, userObject, null, null);
                        }                      
                    }
                }
            }
            catch (StackExchange.Redis.RedisTimeoutException ex)
            {
                
            }
            catch (Exception ex)
            {
               
            }
        }
  1. 将数据插入列表
   public void InsertIntoList(byte[] messageToSend,bool isLoginRequest,string loginID)
        {
            try
            {
                IDatabase database = connection.GetDatabase();
                database.ListRightPush(ConfigurationService.ListToInsertRequest, messageToSend);
            }
            catch (RedisTimeoutException ex)
            {
            }
            catch (Exception ex)
            {
            }
        }

创建连接后,我每 10 毫秒启动一个 System.timer 调用 FetchListToProcess() 方法,该方法检查列表中是否存在任何数据,如果存在,它会相应地获取和处理。

我遇到了应用程序随机记录 RedisTimeout 异常的问题:

Error Messg :: Timeout performing LLEN (5000ms), next: LLEN ROUTER_IEORALG9, inst: 2, qu: 0, qs: 40, aw: False, rs: ReadAsync, ws: Idle, in: 0, in-pipe: 0, out-pipe: 0, serverEndpoint: 192.168.37.182:8081, mgr: 10 of 10 available, clientName: IETRD-15628-2, IOCP: (Busy=1,Free=999,Min=8,Max=1000), WORKER: (Busy=20,Free=32747,Min=8,Max=32767), v: 2.0.601.3402 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
03:29:26.93 :: Stack Trace ::    at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\ConnectionMultiplexer.cs:line 2239
   at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisBase.cs:line 54
   at StackExchange.Redis.RedisDatabase.ListLength(RedisKey key, CommandFlags flags) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisDatabase.cs:line 943
   at BL.RedisConnection.FetchListToProcess()
03:29:27.43 :: Method Name :: Redis --> RedisTimeoutException
03:29:27.43 :: Error Messg :: Timeout performing LLEN (5000ms), next: LLEN ROUTER_IEORALG9, inst: 3, qu: 0, qs: 41, aw: False, rs: ReadAsync, ws: Idle, in: 0, in-pipe: 0, out-pipe: 0, serverEndpoint: 192.168.37.182:8081, mgr: 10 of 10 available, clientName: IETRD-15628-2, IOCP: (Busy=0,Free=1000,Min=8,Max=1000), WORKER: (Busy=21,Free=32746,Min=8,Max=32767), v: 2.0.601.3402 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
03:29:27.43 :: Stack Trace ::    at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\ConnectionMultiplexer.cs:line 2239
   at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisBase.cs:line 54
   at StackExchange.Redis.RedisDatabase.ListLength(RedisKey key, CommandFlags flags) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisDatabase.cs:line 943
   at BL.RedisConnection.FetchListToProcess()
03:29:28.94 :: Method Name :: Redis --> RedisTimeoutException
03:29:28.94 :: Error Messg :: Timeout performing LLEN (5000ms), next: LLEN ROUTER_IEORALG9, inst: 1, qu: 0, qs: 44, aw: False, rs: ReadAsync, ws: Idle, in: 0, in-pipe: 0, out-pipe: 0, serverEndpoint: 192.168.37.182:8081, mgr: 10 of 10 available, clientName: IETRD-15628-2, IOCP: (Busy=0,Free=1000,Min=8,Max=1000), WORKER: (Busy=22,Free=32745,Min=8,Max=32767), v: 2.0.601.3402 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
03:29:28.94 :: Stack Trace ::    at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\ConnectionMultiplexer.cs:line 2239
   at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisBase.cs:line 54
   at StackExchange.Redis.RedisDatabase.ListLength(RedisKey key, CommandFlags flags) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisDatabase.cs:line 943
   at BL.RedisConnection.FetchListToProcess()
03:29:29.36 :: Method Name :: Redis --> RedisTimeoutException
03:29:29.36 :: Error Messg :: Timeout performing LLEN (5000ms), next: LLEN ROUTER_IEORALG9, inst: 2, qu: 0, qs: 45, aw: False, rs: ReadAsync, ws: Idle, in: 0, in-pipe: 0, out-pipe: 0, serverEndpoint: 192.168.37.182:8081, mgr: 10 of 10 available, clientName: IETRD-15628-2, IOCP: (Busy=0,Free=1000,Min=8,Max=1000), WORKER: (Busy=22,Free=32745,Min=8,Max=32767), v: 2.0.601.3402 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
03:29:29.36 :: Stack Trace ::    at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\ConnectionMultiplexer.cs:line 2239
   at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisBase.cs:line 54
   at StackExchange.Redis.RedisDatabase.ListLength(RedisKey key, CommandFlags flags) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisDatabase.cs:line 943
   at BL.RedisConnection.FetchListToProcess()
03:29:29.42 :: Method Name :: Redis --> RedisTimeoutException
03:29:29.42 :: Error Messg :: Timeout performing LLEN (5000ms), next: LLEN ROUTER_IEORALG9, inst: 3, qu: 0, qs: 46, aw: False, rs: ReadAsync, ws: Idle, in: 0, in-pipe: 0, out-pipe: 0, serverEndpoint: 192.168.37.182:8081, mgr: 10 of 10 available, clientName: IETRD-15628-2, IOCP: (Busy=1,Free=999,Min=8,Max=1000), WORKER: (Busy=22,Free=32745,Min=8,Max=32767), v: 2.0.601.3402 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
03:29:29.42 :: Stack Trace ::    at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\ConnectionMultiplexer.cs:line 2239
   at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisBase.cs:line 54
   at StackExchange.Redis.RedisDatabase.ListLength(RedisKey key, CommandFlags flags) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisDatabase.cs:line 943
   at BL.RedisConnection.FetchListToProcess()

以及插入列表方法

03:29:26.42 :: Method Name :: RedisConnection --> InsertIntoList
03:29:26.42 :: Error Messg :: Timeout performing RPUSH (5000ms), next: LLEN ROUTER_IEORALG9, inst: 1, qu: 0, qs: 35, aw: False, rs: ReadAsync, ws: Idle, in: 0, in-pipe: 0, out-pipe: 0, serverEndpoint: 192.168.37.182:8081, mgr: 10 of 10 available, clientName: IETRD-15628-2, IOCP: (Busy=1,Free=999,Min=8,Max=1000), WORKER: (Busy=18,Free=32749,Min=8,Max=32767), v: 2.0.601.3402 (Please take a look at this article for some common client-side issues that can cause timeouts: https://stackexchange.github.io/StackExchange.Redis/Timeouts)
03:29:26.42 :: Stack Trace ::    at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\ConnectionMultiplexer.cs:line 2239
   at StackExchange.Redis.RedisBase.ExecuteSync[T](Message message, ResultProcessor`1 processor, ServerEndPoint server) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisBase.cs:line 54
   at StackExchange.Redis.RedisDatabase.ListRightPush(RedisKey key, RedisValue value, When when, CommandFlags flags) in C:\projects\stackexchange-redis\src\StackExchange.Redis\RedisDatabase.cs:line 1004
   at BL.RedisConnection.InsertIntoList(Byte[] messageToSend, Boolean isLoginRequest, String loginID)

此异常停止获取数据,并且对于不同的用户来说非常随机。对于某些人来说,它会持续到 2-3 分钟,而对于其他人来说,它可能会在 30-40 秒后停止。以前它同时发生在所有连接的用户身上,但现在随机发生在随机数量的用户身上。大约 5-10 个应用程序连接在这些 redis 端口上。我们使用单个列表插入服务器应用程序读取的数据和每个连接的用户单独的列表来获取数据。

我尝试阅读和实施异常详细信息下链接中提到的选项,但没有运气。请建议我做错了什么?是实施还是有其他问题?

问候,
蜜糖

标签: c#redisstackexchange.redis

解决方案


推荐阅读