使用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 -q -n -c -d
由于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异常目前已排除。
2016-10-17 补充
StackExchange.Redis客户端(V1.1.608)经测试有这么一个特质,即,由complexer单例对象创建的IDatabase对象,在产生Timeout异常后会导致这个complexer单例对象超时,即由其创建的新的IDatabase对象也会继续Timeout,相当蛋疼。。。
实际使用过程中,由于网络各种原因,出现Timeout异常难免,但是无法恢复确实很麻烦。测试complexer对象无法dispose,close后重建。。
使用StackExchange.Redis客户端进行Redis访问出现的Timeout异常排查的更多相关文章
- 大数据学习day31------spark11-------1. Redis的安装和启动,2 redis客户端 3.Redis的数据类型 4. kafka(安装和常用命令)5.kafka java客户端
1. Redis Redis是目前一个非常优秀的key-value存储系统(内存的NoSQL数据库).和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list ...
- 【Redis连接超时】记录线上RedisConnectionFailureException异常排查过程
项目架构: 部分组件如下: SpringCloudAlibaba(Nacos+Gateway+OpenFeign)+SpringBoot2.x+Redis 问题背景: 最近由于用户量增大,在高峰时期, ...
- Redis客户端ServiceStack.Redis的简单使用
在nuget中下载ServiceStack.Redis,但是运行之后会出现一个问题: Exception: "Com.JinYiWei.Cache.RedisHelper"的类型初 ...
- Redis 客户端重试指南
本作品采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可. 在互联网服务中,特别是在云环境下,网络及硬件环境复杂,所有应用程序都可能遇到暂时性故障.暂时性故障包括瞬时的网络抖动,服务暂时不可 ...
- 全球领先的redis客户端:SFedis
零.背景 这个客户端起源于我们一个系统的生产问题. 一.问题的发生 在我们的生产环境上发生了两次redis服务端连接数达到上限(我们配置的单节点连接数上限为8000)导致无法创建连接的情况.由于这个系 ...
- Redis 客户端 Jedis、lettuce 和 Redisson 对比
Redis 支持多种语言的客户端,下面列举了部分 Redis 支持的客户端语言,大家可以通过官网查看 Redis 支持的客户端详情. C语言 C++ C# Java Python Node.js PH ...
- Redis客户端命令
Redis客户端命令 Redis 命令用于在 redis 服务上执行操作. 要在 redis 服务上执行命令需要一个 redis 客户端.Redis 客户端在我们之前下载的的 redis 的安装包中. ...
- 一文彻底理解Redis序列化协议,你也可以编写Redis客户端
前提 最近学习Netty的时候想做一个基于Redis服务协议的编码解码模块,过程中顺便阅读了Redis服务序列化协议RESP,结合自己的理解对文档进行了翻译并且简单实现了RESP基于Java语言的解析 ...
- Redis客户端、服务端的安装以及命令操作
目的: redis简介 redis服务端安装 redis客户端安装 redis相关命令操作 redis简介 官网下载(https://redis.io/) Redis 是完全开源免费的,遵守BSD协议 ...
随机推荐
- android handler传递消息机制
当工作线程给主线程发送消息时,因为主线程是有looper的,所以不需要初始化looper,注意给谁发消息就关联谁的handler,此时用的就是主线程的handler handler会把消息发送到Mes ...
- css padding 填充
语法: padding:[ <length> | <percentage> ]{1,4} 默认值:看每个独立属性 适用于:所有元素,除 table-row-group | ta ...
- RubyMine不能调试Rails项目的问题
需要安装debase gem,而且在项目的GemFile中禁用byebug
- mvc页面跳转
用例列举: RedirectToAction: return RedirectToAction("PublicPreview", controllerName, new { id ...
- 利用keepalived和haproxy配置mysql的高可用负载均衡
实验系统:CentOS 6.6_x86_64(2.6.32-504.30.3.el6.x86_64) 实验前提:防火墙和selinux都关闭 实验说明:本实验共有4台主机,IP分配如拓扑 实验软件:k ...
- Postgresql 取随机数
取0和1之间的随机数 SELECT RANDOM(); 取介于两数之间的随机数 SELECT random()*(b-a)+a; ); 取介于两数之间的随机整数 SELECT floor(random ...
- 【Windows编程】系列第九篇:剪贴板使用
上一篇我们学习了常见的通用对话框,本篇来了解剪贴板的使用,它常用于复制粘贴功能. 剪贴板是Windows最早就加入的功能,由于该功能非常实用,我们几乎每天都会使用到.通过剪贴板,我们就可以将数据从一个 ...
- (转)java DecimalFormat用法
DecimalFormat 是 NumberFormat 的一个具体子类,用于格式化十进制数字. DecimalFormat 包含一个模式 和一组符号 符号含义: 0 一个数字 # 一个数字, ...
- 关于域名系统DNS解析IP地址的一些总结
关于域名系统DNS(Domain Name System) 从域名中解析出IP地址. DNS主要由3部分组成: ① 名称解析器(resolver) ② 域名空间(domain name space) ...
- Linux File Recovery Study
Background Today I did stupid things that I went into the ~/Downloads/ and pressed [Alt] + [A] then ...