zoukankan      html  css  js  c++  java
  • .NET中使用Redis总结——2.项目实战

    接上篇.NET中使用Redis总结 —— 1.Redis搭建

    看一些Redis相关资料,.NET 方面ServiceStack.Redis 用的比较多,就直接拿来用了。

    在使用过程中经常过出现假死状态,Redis服务没有挂,只是客户端连不上。

    错误信息如下(这里)

    ServiceStack.Redis.RedisResponseException: Unexpected reply: +OK, sPort: 8223, LastCommand: 

    重启redis就正常了,初步怀疑是连接数超过最大值。

    改为使用链接池

     1 public class RedisCaching
     2     {
     3         /// <summary>
     4         ///     redis配置文件信息
     5         /// </summary>
     6         private static readonly string RedisPath = ConfigurationManager.AppSettings["RedisPath"];
     7 
     8         /// <summary>
     9         /// 
    10         /// </summary>
    11         public static RedisClient Redis;
    12 
    13         /// <summary>
    14         /// 构造方法
    15         /// </summary>
    16         static RedisCaching()
    17         {
    18             var prcm = CreateManager(new string[] { RedisPath }, new string[] { RedisPath });
    19             Redis = prcm.GetClient() as RedisClient;
    20         }
    21 
    22         /// <summary>
    23         /// 创建链接池
    24         /// </summary>
    25         /// <param name="readWriteHosts"></param>
    26         /// <param name="readOnlyHosts"></param>
    27         /// <returns></returns>
    28         public static PooledRedisClientManager CreateManager(string[] readWriteHosts, string[] readOnlyHosts)
    29         {
    30             //支持读写分离,均衡负载
    31             return new PooledRedisClientManager(readWriteHosts, readOnlyHosts, new RedisClientManagerConfig
    32             {
    33                 MaxWritePoolSize = 300,//“写”链接池链接数
    34                 MaxReadPoolSize = 300,//“读”链接池链接数
    35                 AutoStart = true,
    36             });
    37         }
    38 
    39         //static readonly RedisClient redis = new RedisClient("localhost",6379);
    40         //private static readonly RedisClient redis = new RedisClient(RedisPath);//长链接
    41 
    42         public static T Get<T>(string key)
    43         {
    44             return Redis.Get<T>(key);
    45         }
    46 
    47         public static void Set( string key, string value)
    48         {
    49             Redis.Set(key, value);
    50         }
    51 }

    随着业务发展,发现还会出现上面出现的错误。

    使用了lock锁,之后没这种问题发生了。

    这个问题比较严重,每次访问量上去就出现这种错。

    目前在做项目的性能优化,这次每次都lock严重影响效率,得找个方法解决。

    首先分析下Redis 服务有时候是假死,重启下就好了,是不是windows下安装的Redis 不稳定(windows 这锅我不背)?

    或者是RedisClient有问题?

    更换RedisClient成本比较低,可以优先考虑下。

    目前使用的是ServiceStack.Redis 换成 StackExchange.Redis 

    如果使用StackExchange.Redis 项目必须使用.NET 4.5. 要不然会编译会报错。

    StackExchange.Redis 的使用

    引用StackExchange.Redis.dll

    经过一些修改测试后,发现没有之前那种错误,心里窃喜,终于搞定这个问题了。

    最后发现还是 too young too naive

    遇到了新的问

    Timeout performing GET test, inst: 4, mgr: ExecuteSelect, err: never, queue: 12, qu: 0, qs: 12, qc: 0, wr: 0, wq: 0, in: 0, ar: 0, clientName: , IOCP: (Busy=0,Free=1000,Min=4,Max=1000), WORKER: (Busy=11,Free=32756,Min=4,Max=32767) (Please take a look at this article for some common client-side issues that can cause timeouts: http://stackexchange.github.io/StackExchange.Redis/Timeouts)

    No connection is available to service this operation: SETEX test; SocketFailure on Interactive, origin: CheckForStaleConnection, input-buffer: 0, outstanding: 2, last-read: 1s ago, last-write: 0s ago, unanswered-write: 1s ago, keep-alive: 60s, pending: 0, state: ConnectedEstablished, in: 0, ar: 0, last-heartbeat: 0s ago, last-mbeat: 0s ago, global: 0s ago, mgr: RecordConnectionFailed_ReportFailure, err: never; IOCP: (Busy=0,Free=1000,Min=24,Max=1000), WORKER: (Busy=3,Free=32764,Min=24,Max=32767), Local-CPU: n/a   at StackExchange.Redis.ConnectionMultiplexer.ExecuteSyncImpl[T](Message message, ResultProcessor`1 processor, ServerEndPoint server)

    找了一些解决方案,像下面这些方案都没有解决这个问题

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

    Redis 详解 (一) StackExchange.Redis Client

    最后看了这个文章下面的评论有所启发15天玩转redis —— 第七篇 同事的一次缓存操作引起对慢查询的认识

    是因为可能某些查询超过了链接超时时间,Redis是单线程的,阻塞了后面的请求,所以报超时。

    有了这个方向可以着手解决问题。

    1. 拆分大的文件存储
    2. 连接操作超时时间延长
    3. 同步操作时间延长
    4. 增加重试连接次数
     1 private static ConnectionMultiplexer GetManager(string connectionString = null)
     2         {
     3             if (string.IsNullOrEmpty(connectionString))
     4             {
     5                 connectionString = Connstr;
     6             }
     7 
     8             var options = ConfigurationOptions.Parse(connectionString);
     9             options.ConnectTimeout = 1000;//连接操作超时(ms)
    10             options.KeepAlive = 180;//发送消息以帮助保持套接字活动的时间(秒)(默认为60秒)
    11             options.SyncTimeout = 2000;//时间(ms)允许进行同步操作
    12             options.ConnectRetry = 3;//重试连接的次数
    13
    14             return ConnectionMultiplexer.Connect(options);
    15         }

    经过测试上面的问题出现的概率小了很多,但是还是会出现。 

    现在只能定时去监控redis,如果发现异常进行重启进行解决。

    小伙伴们有没有好得解决方案,求分享~

     参考:

      StackExchange.Redis 访问封装类

  • 相关阅读:
    mysql中使用row_number()函数
    Android开发环境的搭建之(二)Android Studio的安装
    Android开发环境的搭建之(一)Java开发环境的安装
    进程与线程
    工作起始之博客搬家
    MapReduce的自制Writable分组输出及组内排序
    map端join和reduce端join的区别
    String.StartsWith 方法
    RPC和心跳机制
    MAPREDUCE中的序列化
  • 原文地址:https://www.cnblogs.com/bigbrid/p/8435453.html
Copyright © 2011-2022 走看看