Redis客户端使用技巧,Redis连接池原理

Redis客户端

Jedis

①Jedis版本
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>2.9.0</version>
</dependency>
②Jedis使用须知

在实际项目中推荐使用try catch finally的形式来进行代码的书写:一方面可以在Jedis出现异常的时候(本身是网络操作),将异常进行捕获或者抛出;另一个方面无论执行成功或者失败,将Jedis连接关闭掉,在开发中关闭不用的连接资源是一种好的习惯。

③连接池JedisPool

Jedis连接池使用方式:


Jedis直连与连接池对比:

Jedis提供了JedisPool这个类作为对Jedis的连接池,同时使用了Apache
的通用对象池工具common-pool作为资源的管理工具
场景一:从连接池中取出Jedis,操作完成后未及时还回连接池

  • 连接池中的资源时有限的,默认连接数只有8个,如果处理完成后不及时归还,并且有大量的请求时,连接资源会很快被消耗完。当超过maxTotal值后调用者所在线程将会阻塞直到有连接还回连接池。
    解决方案:
  • 良好的编码习惯,用完即调用Jedis.close()归还连接。
  • 请求量过大导致调用者所在线程阻塞,可以通过设置blockWhenExhausted=true并且设置maxWaitMillis指定最大等待时间,超过该值后将解除阻塞。
    场景二:连接空闲时间过长导致连接被关闭
  • 连接空闲时间大于客户端设置的timeout时间后,Redis服务器会强制关闭客户端的连接,但是连接池无法获知消息删除无效的连接。如果再从连接池中取出连接进行处理时会抛出异常。
    解决方案:
  • 设置testOnBorrow为true,每次从连接池取连接时会做连接有效性的测试(ping),无效连接会被移除,每次取连接时多执行一次ping命令。
  • 通过设置minEvictableIdleTimeMillis、timeBetweenEvictionRunsMillis定期清理失效连接。minEvictableIdleTimeMillis=1000、timeBetweenEvictionRunsMillis=2000 表示后台线程每2s会执行一次清理任务,将空闲时间>1s的连接移除。
    ** 连接池的配置:**


客户端属性

Redis服务器与客户端连接成功后,都会创建一个client对象保存道歉客户端的信息。可通过输入client list命令查看:



输出每行命令都是代表一个客户端信息,每行中都有十几个属性,它们是客户端的执行状态,理解这些属性对于Redis的开发和运维非常有帮助。

  • addr : 客户端的地址和端口
  • fd : 套接字所使用的文件描述符,普通客户端的fd大于-1。伪客户端的fd是-1,目前Redis服务器会在两个地方用到伪客户端,一个用于载入AOF文件还原数据,另一个用于执行Lua脚本中包含的Redis命令
  • age : 以秒计算的已连接时长
  • idle : 以秒计算的空闲时长
  • flags : 客户端 flag
  • db : 该客户端正在使用的数据库 ID
  • sub : 已订阅频道的数量
  • psub : 已订阅模式的数量
  • multi : 在事务中被执行的命令数量
  • qbuf : 查询缓冲区的长度(字节为单位, 0 表示没有分配查询缓冲区)
  • qbuf-free : 查询缓冲区剩余空间的长度(字节为单位, 0 表示没有剩余空间)
  • obl : 输出缓冲区的长度(字节为单位, 0 表示没有分配输出缓冲区)
  • oll : 输出列表包含的对象数量(当输出缓冲区没有剩余空间时,命令回复会以字符串对象的形式被入队到这个队列里)
  • omem : 输出缓冲区和输出列表占用的内存总量,单位byte
  • events : 文件描述符事件,r/w分别代表客户端套接字可读和科协
  • cmd : 最近一次执行的命令,不含参数

输入缓冲区:qbuf、qbuf-free

Redis为每个客户端分配了输入缓冲区,作用是将客户端发送的命令临时保存,同时会从输入缓冲区读取命令并执行,它为Redis服务器提供了缓冲功能。
Redis无法配置输入缓冲区的大小,输入缓冲区会根据输入内容大小的不同动态调整,但是总体大小不能超过1G。


输入缓存区使用不当产生的问题:

  • 客户端的输入缓冲区超过1G,客户端将会被强制关闭。
  • 输入缓冲区不受maxmemory控制,如果redis实例的maxmemory设置了1G,已经存储800M数据, 如果此时输入缓冲区使用了500M,将总内存将超过maxmemory,可能会产生数据丢失、键值淘汰、OOM等情况
    产生的原因:
  • redis处理速度跟不上输入缓冲区的输入速度,例如存在bigkey,慢查询等原因导致命令执行的时间变长。
  • 写入命令量非常大,但此时redis服务器在执行持久化导致阻塞无法处理命令,导致命令大量积压在输入缓存区中。
    解决方案:
  • client list 查看qbuf、qbuf-free来定位存在问题的客户端,分析原因加以处理。
  • info clients定期监控client_biggest_input_buf,设置预警阀值超过时发送报警邮件或短信 。
命令参数

在服务器将客户端发送deep命令请求保存到输入缓冲区后,服务器对命令请求的内容进行解析得出命令参数以及命令参数的个数分别保存到客户端的argv和argc中。
client对象属性:

  • agrv是一个数组,数组中的每项都是一个字符串对象,其中argv[0]是命令,之后的其他项时传给命令的参数。
  • argc负责记录argv数组的长度。
  • cmd命令表字典结构,key是命令的名字,值时redisCommand对象。redisCommand中有命令实现方法、命令接收的参数个数、命令的总执行次数和总消耗时长等统计信息。命令表的查找操作不区分输入字母的大小写。

    输出缓冲区:obl、oll、omem
    Redis为每个客户端分配了输出缓冲区,作用是保存命令执行的结果返回给客户端为Redi与客户端交互返回结果提供了缓冲功能。
    输出缓冲区的容量可以通过参数client-output-buffer-limit来进行设置。输出缓冲区不受maxmemory控制,如果redis使用内存总量+输出缓冲区的容量>maxmemory时,会产生数据丢失、键值淘汰、OOM等情况。
    配置:
client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
  • <class>:客户端类型,分为三种。a)normal:普通客户端;b)slave:slave客户端,用于复制;c)pubsub:发布订阅客户端。
  • <hard limit>:如果客户端使用的输出缓冲区大于<hard limit>,客户端会被立即关闭。
  • <soft limit>和<soft seconds>:如果客户端使用的输出缓冲区超过了<soft limit>并且持续了<soft limit>秒,客户端会被立即关闭。
    输出缓冲区按客户端的不同分为三种:普通客户端、发布订阅客户端、slave客户端:

    ** 输出缓冲区有两部分组成:固定缓冲区(16KB)和动态缓冲区:**
  • 固定缓冲区用于保存那些长度比较小的回复,比如OK、简短的字符串值、整数值、错误回复等。
  • 可变大小的缓冲区用于保存那些长度比较大的回复,比如一个非常长的字符串值,一个有很多元素组成的集合或列表。
    client对象的结构:

    固定缓冲区使用的是字节数组,动态缓冲区使用的是链表。当固定缓冲区存满后会将Redis新的返回结果存放在动态缓冲区的队列中,队列中的每个对象就是每个返回结果。

    解决方案:
  • 通过定期执行client list命令,收集obl、oll、omem找到异常的连接记录并分析,最终找到可能出问题的客户端。
  • info clients定期监控client_longest_output_list代表输出缓冲区列表最大对象数,设置预警阀值超过时发送报警邮件或短信 。
    合理配置普通客户端输出缓冲区的大小。
  • 如果master节点写入较大,适当增大slave的输出缓冲区的,slave客户端的输出缓冲区可能会比较大,一旦slave客户端连接因为输出缓冲区溢出被kill,会造成复制重连。
  • 限制容易让输出缓冲区增大的命令,例如,高并发下的monitor命令就是一个危险的命令。
  • 及时监控内存,一旦发现内存抖动频繁,可能就是输出缓冲区过大。
    客户端的存活状态
    client list中的age和idle分别代表当前客户端已经连接的时间和最近一次的空闲时间。当age等于idle时,说明连接一直处于空闲状态。
    客户端的限制maxclients和timeout
    maxclients参数来限制最大客户端连接数,一旦连接数超过maxclients,新的连接将被拒绝。maxclients默认值是10000,可以通过info clients来查询当前Redis的连接数。
    某些情况由于业务方使用不当(例如没有主动关闭连接)可能存在大量idle连接,因此Redis提供了timeout(单位为秒)参数来限制连接的最大空闲时间合理使用有限的资源,一旦客户端连接的idle时间超过了timeout,连接将会被关闭。
    Redis的默认配置给出的timeout=0,客户端不会因超时而关闭。

客户端类型

客户端监控

  • connected_clients:代表当前Redis节点的客户端连接数,需要重点监控,一旦超过maxclients,新的客户端连接将被拒绝。
  • client_longest_output_list:当前所有输出缓冲区中队列对象个数的最大值。
  • client_biggest_input_buf:当前所有输入缓冲区中占用的最大容量。
  • blocked_clients:正在执行阻塞命令(例如blpop、brpop、brpoplpush)的客户端个数。
  • total_connections_received(info stats):Redis自启动以来处理的客户端连接数总数。
  • rejected_connections:Redis自启动以来拒绝的客户端连接数,需要重点监控。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 客户端管理 Redis提供了客户端相关 API对其状态进行监控和管理,本节将深入介绍各个API的使用方法以及开发运...
    linuxzw阅读 679评论 0 3
  • Redis提供了客户端相关API对其状态进行监控和管理 1.客户端API 1.client list client...
    huxt阅读 1,420评论 0 1
  • 客户端通信协议 一,客户端与服务端之间的通信协议是在TCP协议之上构建的。二,Redis制定了RESP(REdis...
    何何与呵呵呵阅读 800评论 0 2
  • NOSQL类型简介键值对:会使用到一个哈希表,表中有一个特定的键和一个指针指向特定的数据,如redis,volde...
    MicoCube阅读 3,936评论 2 27
  • redis连接建立 Redis Redis 通过监听一个 TCP 端口或者 Unix socket 的方式来接收来...
    tracy_668阅读 1,896评论 0 4