欢迎来到课桌文档! | 帮助中心 课桌文档-建筑工程资料库
课桌文档
全部分类
  • 党建之窗>
  • 感悟体会>
  • 百家争鸣>
  • 教育整顿>
  • 文笔提升>
  • 热门分类>
  • 计划总结>
  • 致辞演讲>
  • 在线阅读>
  • ImageVerifierCode 换一换
    首页 课桌文档 > 资源分类 > DOCX文档下载  

    Redis常见客户端异常汇总(Jedis篇).docx

    • 资源ID:1425680       资源大小:22.27KB        全文页数:7页
    • 资源格式: DOCX        下载积分:5金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要5金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    Redis常见客户端异常汇总(Jedis篇).docx

    JediS是RediS的java版本的客户端实现。在RediS客户端的使用过程中,无论是客户端使用不当或者RediS服务端出现问题,客户端会反应出一些异常,本文分析了Jedis使用过程中常见的异常情况。一、无法从连接池获取到连接JediSPooI中的JediS对象个数是有限的,默认是8个。这里假设使用的默认配置,如果有8个JediS对象被占用,并且没有归还,如果调用者还要从JediSPoOl中借用Jedis,就需要进行等待(例如设置了maxWaitMillis>O),如果在maxWaitMillis时间内仍然无法获取到Jedis对象就会抛出如下异常。redis.clients.jedis.exceptions.JedisconnectionExceptionzcouldnotgetaresourcefromthepool.Causedbyijava.Uti1.NosuchElementExceptionzTmons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:449)还有一种情况,就是设置了blockWhenExhausted=false,那么调用者发现池子中没有资源时,会立即抛出异常不进行等待下面的异常就是blockWhenExhausted=false时的效果。redis.clients.jedis.exceptions.JedisconnectionExceptionzcouldnotgetaresourcefromthepool.Causedby:java.util.NoSuchElementException:Pmons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:464)对于这个问题,需要重点讨论的是为什么连接池没有资源了,造成没有资源的可能的原因非常多1 .客户端:高并发下连接池设置过小,出现供不应求,所以会出现上面的错误,但是正常情况下只要比默认的最大连接数(8个)多一些即可,因为正常情况下JediSPOoI以及Jedis的处理效率足够高。2 .客户端:没有正确使用连接池,比如没有进行释放,例如下面代码所示:定义JediSPOol,使用默认的连接池配置。GenericObjectPoolConfigpoolConfig=newGenericObjectPoolConfig();JedisPooljedisPool=newJedisPool(poolConfig,"l27.0.0.,6379)jJedisPool借用8次连接,但是没有执行归还操作。for(inti=0;i<8;i+)Jedisjedis=null;tryjedisjedisPool.getResource();jedis.ping();Catch(Exceptione)e.printStackTrace();)当调用者再向连接池借用Jedis时(如下操作),就会抛出异常:jedisPool.getResource().ping();3 .客户端:存在慢查询操作,这些慢查询持有的Jedis对象归还速度会比较慢,造成池子满了。4 .服务端:客户端是正常的,但是RediS服务端由于一些原因造成了客户端命令执行过程的阻塞,也会使得客户端抛出这种异常。可以看到造成这个异常的原因是多个方面的,不要被异常的表象所迷惑,而且并不存在万能钥匙能解决所有问题,开发和运维只能不断加强对于RediS的理解,顺藤摸瓜逐渐找到问题所在。二、客户端读写超时JediS在调用RediS时,如果出现了读写超时后,会出现下面的异常:redis.clients.jedis.exceptions.JedisConnectionException:.SocketTimeoutExceptioniReadtimedout造成该异常的原因也有以下几种:读写超时设置的过短。命令本身就比较慢。客户端与服务端网络不正常。Redis自身发生阻塞。三、客户端连接超时JediS在调用RediS时,如果出现了读写超时后,会出现下面的异常:redis.clients.jedis.exceptions.JedisConnectionExceptionJ.SocketTimeoutExceptioniconnecttimedout造成该异常的原因也有以下几种:连接超时设置的过短。RediS发生阻塞,造成tcp-backlog已满,造成新的连接失败。客户端与服务端网络不正常。四、客户端缓冲区异常JediS在调用RediS时,如果出现客户端数据流异常,会出现下面的异常。redis.clients.jedis.exceptions.JedisConnectionException:Unexpectedendofstream造成这个异常原因可能有如下几种:1 .输出缓冲区满。例如将普通客户端的输出缓冲区设置为IMIM60:configsetclient-output-buffer-limit,'nonall048576104857660slave2684354566710886460PUbSUb33554432838860860”如果使用get命令获取一个bigkey(例如3M),就会出现这个异常。2 .长时间闲置连接被服务端主动断开,可以查询timeout配置的设置以及自身连接池配置是否需要做空闲检测。3 .不正常并发读写:JediS对象同时被多个线程并发操作,可能会出现上述异常。五、1.Ua脚本正在执行如果Redis当前正在执行1.ua脚本,并且超过了lua-time-limit,此时JediS调用RediS时,会收到下面的异常。对于如何处理这类问题(1.UaIUa-time-limit配置之前章节已经介绍了)redis.clients.jedis.exceptions.JedisDataException:BUSYRedisisbusyrunningascript.YoucanonlycallSCRIPTKI1.1.orSHUTDOWNNOSAVE.六、RediS正在加载持久化文件JediS调用RediS时,如果RediS正在加载持久化文件,那么会收到下面的异常。redis.clients.jedis.exceptions.JedisDataExceptioni1.OADINGRedisisloadingthedatasetinmemory七、Redis使用的内存超过maxmemory配置Jedis调用Redis执行写操作时,如果Redis的使用内存大于maxmemory的设置,会收到下面的异常,此时应该调整maxmemory并找到造成内存增长的原因(maxmemory之前章节已经介绍了)redis.clients.jedis.exceptions.JedisDataException:OOMcommandnotallowedwhenusedmemory>,maxmemory'.八、客,端连接数过大如果客户端连接数超过了maxclients,新申请的连接就会出现如下异常:redis.clients.jedis.exceptions.JedisDataException:ERRmaxnumberofclientsreached此时新的客户端连接执行任何命令,返回结果都是如下:127.0.0.k6379>gethello(error)ERRmaxnumberofclientsreached这个问题可能会比较棘手,因为此时无法执行RediS命令,一般来说可以从两个方面进行着手。1 .客户端:如果maxclients参数不是很小的话,应用方的客户端连接数基本不会超过maxclients,通常来看是由于应用方对于Redis客户端使用不当造成的。此时如果应用方是分布式结构的话,可以通过下线部分应用节点(例如占用连接较多的节点),使得Redis的连接数先降下来。从而让绝大部分节点可以正常运行,此时在再通过查找程序bug或者调整maxclients进行问题的修复。2 .服务端:如果此时客户端无法处理,而当前Redis为高可用模式(例如RedisSentinel和RedisCluster),可以考虑将当前Redis做故障转移。此问题不存在确定的解决方式,但是无论从哪个方面进行处理,故障的快速恢复极为重要,当然更为重要的是找到问题的所在,否则一段时间后客户端连接数依然会超过maxclientso附GenericobjectPoolConfig的重要属性序号参数名含义默认值1maxActive连接池中最大连接数82maxldle连接池中最大空闲的连接数83minldle连接池中最少空闲的连接数04maxWaitMillis当连接池资源用尽后,调用者的最大等待时间(单位为毫秒),一般不建议使用默认值-1:表示永远不超时,一直等。5JmxEnabled是否开启jmx监控,如果应用开启了jmx端口并且JmxEnabled设置为true,就可以通过jconsole或者jvisualvm看到关于连接池的相关统计,有助于了解连接池的使用情况,并且可以针对其做监控统计true6minEvictableIdleTimcMillis连接的最小空闲时间,达到此值后空闲连接将被移除30分钟7numTestsPerEvictionRun做空闲连接检测时,每次的采样数38IestOnBorrow向连接池借用连接时是否做连接有效性检测(Ping),无效连接会被移除,每次借用多执行一次ping命令false序号参数名含义默认值9IestOnRetum向连接池归还连接时是否做连接有效性检测(Ping),无效连接会被移除,每次归还多执行一次ping命令false10IestWhileIdIe向连接池借用连接时是否做连接空闲检测,空闲超时的连接会被移除false11timeBetweenEvictionRunsMillis空闲连接的检测周期(单位为毫秒)-1:表示不做检测12blockWhenExhausted当连接池用尽后,调用者是否要等待,这个参数是和maxWaitMillis对应的,只有当此参数为true时,InaxWaitMillis才会生效Redis客户端处理介绍了有关RediS如何从网络层的角度处理客户端的信息:连接,超时,缓冲区以及其他类似主题。本文包含的信息仅适用于Redis版本2.6或更高版本。如何接受客户端的连接?Redis通过监听一个TCP端口或者Unixsocket的方式来接收客户端的连接,当一个新的客户端连接建立后,RedisServer会执行以下一些操作:客户端socket会被设置为非阻塞模式,因为Redis在网络事件处理上采用的是非阻塞多路复用模型。设置TCP_N0DE1.AY属性,禁用Nagle算法,确保在我们的连接不要延迟创建一个可读的文件事件,以便于SOCket传送新数据时立即收集客户端查询初始化客户端连接后,Redis核实可能同时处理的连接数是否已达到上限,这个上限是在RediS.conf配置文件中通过maxclients命令来设置的。万一因为已达到最大连接数的上限而不能接受当前的连接时,Redis会给客户端发送一个错误信息,告知当前的情况并立即关闭连接。即使连接关闭,客户端还是会收到该错误信息,因为新的SOCket输出缓冲足够容纳这个错误信息,所以,内核将处理错误信息的传输。按什么顺序服务客户呢?这个顺序受客户端socket文件描述符和内核报告事件顺序的组合决定,因此顺序将被视为未指定。然而当有多个客户端Redis将下面两件事:每当有新的东西从客户端读取时,只执行一次read()系统调用,为了保证如果我们有多个客户端连接,一些苛刻的客户端高频率的发送命令时,其他客户端不会受到惩罚,也不会遇到延迟数据不佳的情况。当然,一旦这次read。调用完成后,它里面无论包含多少个命令,都会被一次性顺序地执行。这样就保证了对各个客户端命令的公平对待。关于最大连接数maxclients在Redis2.4中,同时处理的最大连接数是被直接硬编码在代码里面的而在2.6版本中这个值变成可配置的:默认值是100o0,也可以在redis.conf中通过maxclients指令的对这个值进行修改。当然,这个值只是Redis一厢情愿的值,Redis还会照顾到系统本身对进程使用的文件描述符数量的限制。在启动时RediS会检查系统的SofHimi3以查看打开文件描述符的个数上限。如果系统设置的数字,小于咱们希望的最大连接数加32,那么这个maxclients的设置将不起作用,Redis会按系统要求的来设置这个值。(加32是因为Redis内部会使用最多32个文件描述符,所以连接能使用的相当于所有能用的描述符号减32)o当上面说的这种情况发生时(maxclients设置后不起作用的情况),RediS的启动过程中将会有相应的日志记录。比如下面命令希望设置最大客户端数量为100000,所以RediS需要100000+32个文件描述符,而系统的最大文件描述符号设置为10144,所以Redis只能将maxclients设置为10144-32=10112。$./redis-servermaxclients1000004142223Janl1:28:33.179#Unabletosetthemaxnumberoffileslimittol00032(Invalidargument),Settingthemaxclientsconfigurationto10112.所以说当你想设置maxclients值时,最好顺便修改一下你的系统设置,当然,养成看日志的好习惯也能发现这个问题。具体的设置方法就看你个人的需求了,你可以只修改此次会话的限制,也可以直接通过SySCtI修改系统的默认设置。如:ulimit-Sn1OOOO0#ThiSWillonIyWorkifharcnimitiSbigenoUgh.sysctl-wfs.file-max=1(X)OOO输出缓冲区大小限制(redisserver的数据返回)对于RediS的输出(也就是命令的返回值)来说,其大小经常是变化的,可能是一个简单的命令,能够产生体积庞大的返回数据。另外也有可能因为执行命令太多,产生的返回数据的速率超过了往客户端发送的速率,像PubZSub万一客户端不能快速的消费消息的情况是真实发生的。这两种情况就促使客户端输出缓冲不断增长并消耗大量内存,因此Redis默认设置输出缓冲大小限制,达到上限时就关闭连接,在日志打一个log。有不同的输出缓冲区大小限制,限制方式有两种:一种是硬限制,当某一个客户端的缓冲区超过某一大小时,直接关闭掉这个客户端连接另一种是软限制,当某一个客户端的缓冲区持续一段时间占用空间过大时,也直接关闭掉客户端连接。比如一个30MB10s的软限制意味着,如果一个客户端输出缓冲大小32MB并持续10s,连接就关闭。对于不同客户端的策略如下:普通客户端,限制为0,也就是不限制,因为普通客户端通常采用阻塞式的消息应答模式,如:发送请求,等待返回,再发请求,再等待返回。这种模式通常不会导致输出缓冲区的堆积膨胀。PUb/Sub客户端,大小限制是32m,当输出缓冲区超过32m时,会关闭连接。持续性限制是,当客户端缓冲区大小持续60秒超过8m,也会导致连接关闭。Slave客户端,大小限制是256m,持续性限制是当客户端缓冲区大小持续60秒超过64m时,关闭连接。上面三种规则都是可配置的。可以通过configset命令或者修改redis.conf文件来配置。查询缓冲区硬限制(输入,即客户端命令输入)每个客户端也受限于查询缓冲区。Redis对输入缓冲区大小的限制比较暴力,当客户端传输的请求大小超过IG时,服务端会直接关闭连接。这种方式可以有效防止一些客户端或服务端bug导致的输入缓冲区过大的问题。Client超时对当前的RediS版本来说,服务端默认是不会关闭长期空闲的客户端的。但是你可以修改默认配置来设置你希望的超时时间。比如客户端超过多长时间无交互,就直接关闭。同理,这也可以通过CoNFIGSET命令或者修改redis.conf文件来配置。值得注意的是,超时时间的设置,只对普通客户端起作用,对Pub/Sub客户端来说,长期空闲状态是正常的。即使默认情况下,连接不会超时,但有两个条件可以设置超时:任务严重的应用,客户端软件中的bug可能会使Redis服务器空闲连接饱和,导致服务中断。作为一种调试机制,为了能够与服务器连接,如果客户端软件中的bug使服务器闲置连接饱和,使得不可能与服务器交互。另外,实际的超时时间可能不会像设定的那样精确,这是因为RediS并不会采用计时器或者轮训遍历的方法来检测客户端超时,而是通过一种渐近式的方式来完成,每次检查一部分。所以导致的结果就是,可能你设置的超时时间是IOs,但是真实执行的时间是超时12s后客户端才被关闭。C1.IENT命令RediS的CUENT命令能够实现三种功能:检查连接的状态,杀掉某个连接以及为连接设置名字。C1.IENT1.IST命令能够获取当前所有客户端的状态,使用方法如下:redis127.0.0.1:6379>clientlistaddr=127.0.0.l:52555fd=5name=age=855idle=0flags=Ndb=0sub=0psub=0multi=-1qbuf0qbuf-free=32768obl=0oll=0omem=0events=rcmd=clientaddr=127.0.0.1:52787fd=6name=age=6idle=5flags=Ndb=0sub=0psub=0multi=-lqbuf=0qbuf-free=0obl=0oll=0omem=0eve11ts=rcmd=ping如上面命令的输出可知,目前此RediS有两个客户端连接,每一行表示一个连接的各项信息:addr:客户端的TCP地址,包括IP和端口fd:客户端连接socket对应的文件描述符句柄号name:连接的名字,默认为空,可以通过CUENTSETNAME设置age:客户端存活的秒数idle:客户端空闲的秒数flags:客户端的类型(N表示普通客户端)O:theclientisaslaveinMONITORmodeSitheclientisanormalslaveserverMRheclientisamasterXitheclientisinaMu1.TlZEXECcontextb:theclientiswaitinginablockingoperationi:theclientiswaitingforaVMI/O(deprecated)Cliawatchedkeyshasbeenmodified-EXECwillfailCzconnectiontobeclosedafterwritingentirereplyUitheclientisunblockedUitheclientisconnectedviaaUnixdomainsocketr:theclientisinreadonlymodeagainstaclusternodeAzconnectiontobeclosedASAPNznospecificflagsetOmem:输出缓冲区的大小Cmd:最后执行的命令名称当你通过上面命令获取到客户端列表后,就可以通过C1.IENTKI1.1.命令来杀死指定的连接了。C1.IENTKI1.1.的参数就是上面的addr值。如上面提到的C1.IENTSETNAME和CUENTGETNAME可以用来设置或获取一个连接的客户端名字。从4.0后客户端名字也将展示的S1.OW1.OG中,这样定位问题也将更方便了。TCPkeepalive-keepalive,是在TCP中一个可以检测死连接的机制。3.2及以上版本默认启用TCPkeePaliVe(SC1.KEEPA1.lVESOCketOPtiOn),设置300so这个选项对于检测死掉的客户端是有用Q(即使他们看起来连接也无法联系的客户)。此外,如果在客户端和服务器之间存在需要查看一些流量的网络设备才能使连接处于打开状态,该选项将防止意外的连接关闭事件。

    注意事项

    本文(Redis常见客户端异常汇总(Jedis篇).docx)为本站会员(夺命阿水)主动上传,课桌文档仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知课桌文档(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-1

    经营许可证:宁B2-20210002

    宁公网安备 64010402000986号

    课桌文档
    收起
    展开