第一个redis应用方法导致的提示redis LRANGE命令超时问题的解决
来源:互联网 发布:无损音乐播放软件 编辑:程序博客网 时间:2024/06/07 11:11
我的第一个redis应用的方法代码如下:
public List<QuestionsLibrary> GetRedisQuestionsLibraryList() { var qlist = RedisHelper.ListRange<QuestionsLibrary>(RedisKey.RedisQuestionsLibraryList); if (qlist == null || qlist.Count() <= 0) { List<QuestionsLibrary> list = new QuestionsLibraryService().GetNolock(m => true).ToList(); RedisHelper.ListRightPush(RedisKey.RedisQuestionsLibraryList, list); return list; } else { return RedisHelper.ListRange<QuestionsLibrary>(RedisKey.RedisQuestionsLibraryList); } }
此方法在使用中通过对服务器的监察,发现cpu从原来的1%左右飙升到40-50%。而且在错误日志出现了大量有关redis超时提示。错误提示代码如下:
Timeout performing LRANGE Redis:QuestionsLibraryList, inst: 7, queue: 8, qu: 0, qs: 8, qc: 0, wr: 0, wq: 0, in: 2944, ar: 0, clientName: iZ25f3l6awvZ, serverEndpoint: 127.0.0.1:8383, keyHashSlot: 3349, IOCP: (Busy=1,Free=799,Min=8,Max=800), WORKER: (Busy=9,Free=791,Min=8,Max=800) (Please take a look at this article for some common client-side issues that can cause timeouts: http://stackexchange.github.io/StackExchange.Redis/Timeouts)
可以确认这个都是页面调用RedisHelper.ListRange这个方法引起的。从网上扒的资料来看,redis是单进程,单线程的。也就是说,短时间内网站向redis服务发出了大量的ListRange指令。由于指令是在队列中一条一条处理的。导致后面的指令得不到处理。
我又到服务器上打开cmd窗口,然后进入redis命令后输入:
SLOWLOG GET
然后发觉最近的超时命令都是LRANGE,而且每条都超过了10几秒。但我很疑惑,因为我的RedisHelper类是单例连接,使用的都是静态方法和静态属性,静态变量。难道是我使用的GetRedisQuestionsLibraryList() 不是静态方法的缘故?这不科学啊,虽然我这个方法是实例方法。可是这个方法中自redis服务中获取值的方法确实实实在在的静态方法啊。这令我很凌乱,在网上扒资料,并没有找到这块有用的东西。但问题还是要解决。因为没有理论佐证,只好进行尝试。于是我把此方法改为静态属性的形式代码:
protected static List<QuestionsLibrary> RedisQuestionsLibraryList { get { var qlist = RedisHelper.ListRange<QuestionsLibrary>(LMSoft.WebCommon.RedisKey.RedisQuestionsLibraryList); if (qlist == null || qlist.Count() <= 0) { List<QuestionsLibrary> list = new QuestionsLibraryService().GetNolock(m => true).ToList(); RedisHelper.ListRightPush(LMSoft.WebCommon.RedisKey.RedisQuestionsLibraryList, list); return list; } else { return qlist; } } }
然后修改相关调用代码,编译,上传到服务器上进行测试。结果出现了大量的redis的Timeout performing LRANGE Redis超时提示。和原来的错误一样。果断修改为静态方法形式进行测试,代码如下:
protected static List<QuestionsLibrary> GetRedisQuestionsLibraryList() { var qlist = RedisHelper.ListRange<QuestionsLibrary>(LMSoft.WebCommon.RedisKey.RedisQuestionsLibraryList); if (qlist == null || qlist.Count() <= 0) { List<QuestionsLibrary> list = new QuestionsLibraryService().GetNolock(m => true).ToList(); RedisHelper.ListRightPush(LMSoft.WebCommon.RedisKey.RedisQuestionsLibraryList, list); return list; } else { return qlist; } }
protected static List<QuestionsLibrary> RedisQuestionsLibraryList = getRedisQuestionsLibraryList(); private static List<QuestionsLibrary> getRedisQuestionsLibraryList() { var qlist = RedisHelper.ListRange<QuestionsLibrary>(LMSoft.WebCommon.RedisKey.RedisQuestionsLibraryList); if (qlist == null || qlist.Count() <= 0) { List<QuestionsLibrary> list = new QuestionsLibraryService().GetNolock(m => true).ToList(); RedisHelper.ListRightPush(LMSoft.WebCommon.RedisKey.RedisQuestionsLibraryList, list); return list; } else { return qlist; } }
上传上去后,观察网站cpu的使用。又观察错误日志代码。经过一个多小时的跟踪,这次没发现cpu使用大幅上扬的情况,也没发现超时错误。这算是解决了。可是我很无语,你说实例方法调用,会出现大量排队现象,怎么静态方法及静态属性这两种获取方法也出现大量redis排队现象。概念理解的不透么,也只能这样说了。
扒了扒资料也就找到一个似乎能解释通的。提到了静态变量的初始化及赋值。
1、任何带有初始值设定项的静态字段,则在执行该类的静态构造函数时,先要按照文本顺序执行那些初始值设定项
2、如果没有编写静态构造函数,而这时类中包含带有初始值设定的静态字段,那么编译器会自动生成默认的静态构造函数
3、类的静态构造函数在给定应用程序域中至多执行一次:只有创建类的实例或者引用类的任何静态成员才激发静态构造函数
这意味着我上面所写的静态变量的赋值方法,其实在C#的编译器中是自动创建的静态构造函数中完成的赋值操作,并且只执行了一次。。
静态方法及静态属性按我以前的理解,它是所有该类的实例方法都可以使用的,并且在这里的话这个静态方法或者静态属性只调用一次Redis中的LRANGE命令。然而从测试的情况来看,它和实例方法一样,每次使用都要调用一次Redis中的LRANGE命令。我又对静态方法及静态属性的理论解释深入挖掘,发现了一个有意思的解释,就是它是一系列行为的组合。是一个action,也就是动作。那这也意味着每次调用的时候,它里面的一系列操作都要执行一遍。这样就解释通了。由于每次调用静态属性和静态方法,里面的操作都要执行,那自然对Redis的LRANGE命令进行了多次调用操作。然后导致了redis报超时错误。而静态变量由于赋值就进行了一次,也就是Redis的LRANGE命令只调用了一次,所以不会遇到由于大量调用造成超时的问题
- 第一个redis应用方法导致的提示redis LRANGE命令超时问题的解决
- 解决curl超时导致应用崩溃的问题
- 解决curl超时导致应用崩溃的问题
- Tomcat应用报redis超时的故事
- redis超时问题分析
- 如何解决Connect超时导致的阻塞问题
- Redis常用的30个命令
- 关于redis使用set时设置超时时间的问题
- 关于redis使用set时设置超时时间的问题
- 7个Redis的应用场景
- redis的数据类型,命令以及应用场景
- 通过spring-data-redis完成LINDEX, LLEN, LPOP, LPUSH, LRANGE, LREM, LSET, LTRIM, RPOP, RPUSH命令
- redis主从切换需要解决的问题
- Redis中文乱码问题的解决
- redis解决购物车的问题
- 解决 Redis 只读不可写的问题
- 安装redis 遇到的问题及解决
- Redis启动警告问题的解决
- PM2 使用介绍
- 连接池 druid(阿里巴巴的框架)
- maven聚合与继承
- sublime text 3注释快捷键ctrl+/失效解决方案
- nginx的重启
- 第一个redis应用方法导致的提示redis LRANGE命令超时问题的解决
- markdown使用笔记
- Effective Modern C++:Item 2 ->弄清auto类型推断
- NYOJ-34-韩信点兵(数论)
- 游戏开发!!!多学、多练、多想!
- js 单个反斜杠替换
- Android ListView中动态显示和隐藏Header&Footer的方法(转)
- 优雅的开发TableView
- maven上传第三方jar到nexus私服