http://redisbook.readthedocs.io/en/latest/java
redis为何会有高并发问题redis
redis是一种单线程机制的nosql数据库,基于key-value,数据可持久化落盘。因为单线程因此redis自己并无锁的概念,多 个客户端链接并不存在竞争关系,可是利用jedis等客户端对redis进行并发访问时会出现问题。发生链接超时、数据转换错误、阻塞、客户端关闭链接等 问题,这些问题均是因为客户端链接混乱形成。sql
同时,单线程的天性决定,高并发对同一个键的操做会排队处理,若是并发量很大,可能形成后来的请求超时。数据库
在远程访问redis的时候,由于网络等缘由形成高并发访问延迟返回的问题。服务器
解决办法网络
jedis常见错误分析并发
异常代码1:nosql
redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the poolsocket
问题分析:redis.clients.util.Pool.getResource会从JedisPool池中返回一个可用的redis链接,关于JedisPool中可用链接的配置有几个重要的参数以下:高并发
MaxActive:可用链接实例的最大数目,为负数的时候没有限制。
MaxIdle:空闲链接实例的最大数目,为负值时没有限制。
MaxWait:等待获取连接的超时时间。
也就是说当链接池中没有active/idle的链接时,会等待maxWait时间,若是等待超时尚未可用链接,则抛出Could not get a resource from the pool异常。因此为避免这样的错误,
咱们应该根据程序实际状况合理设置这三个参数的值,同时在咱们获取一个链接的程序方法中也应该合理的处理这个异常,当没有链接可用时,等待一段时间再获取也许是个比较好的选择。
异常代码2:
redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out
遇到这个异常,可能会比较疑惑,redis是对内存的操做,速度一个在毫秒级别,在对redis操做出现秒级别的操做时会让人感受疑惑,可是本文开头已经说过了,在一些特殊状况下,redis出现超时并不奇怪。jedis在初始化JedisPool时应该根据实际状况经过redis.clients.jedis.JedisPoolConfig合理设置链接池参数,经过redisPool构造方法,设置socket读取输入InputStream的超时时间。
`pool = new JedisPool(config, host, port, 100000)`;
第四个参数是time out,单位是毫秒。能够经过合理的设置这个值来规避问题。可是这不能彻底解决超时的为题。有些高并发状况下,延时返回时间甚至会达到几十秒的极端状况。 这个问题要经过代码层面解决redis单线程自己不支持锁,在对同一个键进行并发操做会产生竞争的问题。