客户端通信协议
redis客户端和服务端通信协议建立在TCP基础上,并且制定了RESP(Redis Serialization Protocal)序列化协议。其格式大致如下:
|
|
RESP发送命令的格式如下,CRLF代表"\r\n",即换行符
|
|
RESP返回结果类型分为以下五种:
- 状态回复:在RESP中第一个字节为"+"
- 错误回复:在RESP中第一个字节为"-"
- 整数回复:在RESP中第一个字节为":"
- 字符串回复:在RESP中第一个字节为"$"
- 多条字符串回复:在RESP中第一个字节为"*"
Tips:如果有nil值则直接回复返回$-1
Jedis
连接Redis
|
|
- host:Redis服务端IP
- port:Redis服务端端口
- connectionTimeout:客户端连接超时时间
- soTimeout:客户端读写超时时间
连接池 Jedis每次连接会新建一个连接会话然后再断开连接,频繁访问不是非常高效。这时,可以采用Jedis连接池,所有Jedis对象预先放在Jedis pool中,每次要连接Redis,直接从连接池中分配然后再归还,能够有效的管理Redis会话。
|
|
下面是一些常用GenericObjectPoolConfig的属性,可以对连接池进行配置。
参数 | 说明 | 默认值 |
---|---|---|
maxActive | 连接池最大连接数 | 8 |
maxIdle | 连接池最大空闲连接数 | 8 |
minIdle | 连接池最小空闲连接数 | 0 |
maxWaitMillis | 当连接池用尽,最大等待时间(毫秒) | -1(永不超时) |
jmxEnabled | 是否开启jmx,如果开启了jmx端口并且启用该配置就可以通过jconsole看到连接池统计信息 | true |
minEvictableIdleTimeMillis | 连接的最小空闲时间,达到此值空闲连接将被移除 | 1000L * 60L * 30 = 30分钟 |
numTestsPerEvictionRun | 空闲连接检测时的采样数 | 3 |
testOnBorrow | 申请连接池资源时是否做连接有效性验证,无效则移除 | false |
testOnReturn | 归还连接池时是否做有效性验证,无效则移除 | false |
testWhileIdle | 申请连接池资源时是否做连接空闲检测,空闲超时则移除 | false |
timeBetweenEvictionRunsMillis | 空闲连接的检测周期 | -1(不做检测) |
blockWhenExhausted | 连接池用尽时是否等待,配合maxWaitMillis使用 | true |
PipeLine
Jedis也支持通过PipeLine来实现批量操作
|
|
也可以使用syncAndReturnAll()执行并返回结果
Lua
Jedis执行Lua脚本与redis-clo类似,其提供了三个函数来实现Lua脚本的执行
- Object eval(String script,int keyCount,String params)
- Object evalsha(String sha1,int keyCount,String params)
- String scriptLoad(String script)
|
|
redis-py
连接Redis
|
|
PipeLine
redis-py也支持pipeline的方式执行批量语句
|
|
transaction=False表示不开启事务
Lua
redis-py实现执行Lua脚本的方式与redis-cli类似
|
|
客户端管理
通过redis命令client list可以查看所有与Redis连接的客户端信息
|
|
- id:客户端连接唯一标识,随着redis连接自增长,重启后重置为0
- addr:客户端连接的IP和端口
- fd:socket文件描述符,如果fd=-1则表示不是外部客户端而是Redis内部的伪装客户端
- name:客户端名称,可以通过client setName和client getName设置并获取
- qbuf/qbuf-free:分表代表输入缓冲区的总容量及空闲流量。
- obl:输出缓冲区中固定缓冲区长度
- oll:输出缓冲区中动态缓冲区长度
- omem:输出缓冲区使用的字节数
- age/idle:分别代表客户端已经连接的时间和最近一次的空闲时间
- flags:客户端连接标识
- db:当前数据库索引下标
- sub/psub:当前客户段订阅的频道或者模式数量
- multi:当前事务中已执行命令个数
- events:文件描述符事件,r和w分别代表客户都按套接字可读和可写
- cmd:客户端最后一次执行的命令
输入缓冲区
Redis为每个客户端分配了输入缓冲区,将客户端发送的命令临时保存。输入缓冲区大小是根据内容大小动态调整的,但是最大不能超过1G,否则客户端将被关闭。并且输入缓冲区不受maxmemory控制,如果使用不当可能会造成OOM,键值淘汰等情况
输出缓冲区
Redis为每个客户端分配了输出缓冲区,将执行结果保存并返回客户端。可以通过参数client-output-buffer-limit来修改,并且按照客户端的不同分为:普通客户端、发布订阅客户端、slave客户端
|
|
- class:客户端类型:normal为普通客户端,slave为slave客户端,pubsub为发布订阅客户端
- hard limit:如果客户端使用的输出缓冲区大于hard limit,客户端会被立即关闭
- soft limit:如果客户端使用的输出缓冲区大约soft limit并且持续了soft seconds秒,客户端会被立即关闭
实际上,输出缓冲区由两部分组成,固定缓冲区和动态缓冲区,固定缓冲区为16K,用于返回小的执行结果,而动态缓冲区返回较大的结果。结构上,固定缓冲区使用的是bitmaps,动态缓冲区使用的是List。
客户端配置
maxclients:Redis提供了maxclients参数来限制最大客户端连接数,一旦超过新的连接将直接被拒绝。其默认值为10000,大部分场景足够使用了。
timeout:如果数据库存在大量idle空闲状态的会话,可以设置timeout(秒)来限制最大的空闲时间,一旦客户端空闲时间超过了timeout,连接会被关闭。默认为0,也就是不检测空闲超时,建议根据需求设置该参数。
tcp-keepalive:用于检测TCP连接活性检测,默认为0,建议设置为60,表示60秒检测一次。
tcp-backlog:TCP三次握手之后,会将接受的连接放入队列中,tcp-backlog就是队列的大小,默认值为511。该参数会受到操作系统的影响,建议设置somaxconn大于或等于511
|
|
客户端类型
client list中的flag用于标识当前客户端类型,其中都有以下类型。
类型 | 说明 |
---|---|
N | 普通客户端 |
M | 当前客户端是master节点 |
S | 当前客户端是slave节点 |
O | 当前客户端在执行monitor命令 |
x | 当前客户端正在执行事务 |
b | 当前客户端正在等待阻塞事件 |
i | 当前客户端正在等待VM I/O |
d | 一个受监视的key已被修改,exec命令将失败 |
u | 客户端未被阻塞 |
c | 回复完整输出后,关闭连接 |
A | 尽可能快地关闭连接 |
常用命令
client kill可以用于杀掉指定IP地址和端口的客户端
|
|
client pause可以用于阻塞客户端,对slave客户端无效
|
|
monitor用于监控redis正在执行的命令,但其可能因为输出缓冲区暴涨导致使用大量内存,生产环境应当禁止使用