网站建设及宣传管理规定,湛江建设培训学校网站,网站空间购买,合肥中小型企业网站建设方案模板一、client listclient list命令能列出与Redis服务端相连的所有客户端连接信息。例如下面代码是在一个Redis实例上执行client list的结果#xff0c;其中每一行代表一个客户端信息#xff1a;下面将选择几个重要的属性进行说明#xff0c;其余通过表格的形式进行展示①标识其中每一行代表一个客户端信息 下面将选择几个重要的属性进行说明其余通过表格的形式进行展示①标识id、addr、fd、name这四个属性属于客户端的标识id客户端连接的唯一标识这个id是随着Redis的连接自增的重启 Redis后会重置为0addr客户端连接的ip和端口fdsocket的文件描述符与lsof命令结果中的fd是同一个如果fd-1代表当前客户端不是外部客户端而是Redis内部的伪装客户端name客户端的名字后面的client setName和client getName两个命令会对其进行说明②输入缓冲区qbuf、qbuf-freeRedis为每个客户端分配了输入缓冲区它的作用是将客户端发送的命令临时保存同时Redis从会输入缓冲区拉取命令并执行输入缓冲区为客 户端发送命令到Redis执行命令提供了缓冲功能如下图所示client list中qbuf和qbuf-free这两个属性分别代表这个缓冲区的总容量和剩余容量Redis没有提供相应的配置来规定每个缓冲区的大小输入缓冲区会根据输入内容大小的不同动态调整只是要求每个客户端缓冲区的大小不能超过1G超过后客户端将被关闭下面是Redis源码中对于输入缓冲区的硬编码/* Protocol and I/O related defines */
#define REDIS_MAX_QUERYBUF_LEN (1024*1024*1024) /* 1GB max query buffer. */
输入缓冲使用不当会产生两个问题一旦某个客户端的输入缓冲区超过1G客户端将会被关闭输入缓冲区不受maxmemory控制假设一个Redis实例设置了maxmemory为4G已经存储了2G数据但是如果此时输入缓冲区使用了3G已经超过maxmemory限制可能会产生数据丢失、键值淘汰、OOM等情况如下图所示上图的执行效果如下上面已经看到输入缓冲区使用不当造成的危害非常大那么造成输入缓冲区过大的原因有哪些输入缓冲区过大主要是因为Redis的处理速度跟不上输入缓冲区的输入速度并且每次进入输入缓冲区的命令包含了大量 bigkey从而造成了输入缓冲区过大的情况还有一种情况就是Redis发生了阻塞短期内不能处理命令造成客户端输入的命令积压在了输入缓冲区 造成了输入缓冲区过大那么如何快速发现和监控呢监控输入缓冲区异常的方法有两种通过定期执行client list命令收集qbuf和qbuf-free找到异常的连接记录 并分析最终找到可能出问题的客户端。通过info命令的info clients模块找到最大的输入缓冲区例如下面命令中的其中client_recent_max_input_buffer代表最大的输入缓冲区例如可以设置超过10M就进行报警上面两种方法各有自己的优劣势下图对两种方法进行了对比运维提示输入缓冲区问题出现概率比较低但是也要做好防范在开发中要减少bigkey、减少Redis阻塞、合理的监控报警③输出缓冲区obl、oll、omemRedis为每个客户端分配了输出缓冲区它的作用是保存命令执行的结 果返回给客户端为Redis和客户端交互返回结果提供缓冲与输入缓冲区不同的是输出缓冲区的容量可以通过参数client-outputbuffer-limit来进行设置并且输出缓冲区做得更加细致按照客户端的不同分为三种普通客户端、发布订阅客户端、slave客户端。如下图所示client-output-buffer-limit格式如下。参数意义为class客户端类型分为三种。anormal普通客户端b slaveslave客户端用于复制cpubsub发布订阅客户端hard limit如果客户端使用的输出缓冲区大于该值客户端会被立即关闭soft limit和soft seconds如果客户端使用的输出缓冲区超过了并且持续了秒客户端会被立即关闭Redis的默认配置是client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
和输入缓冲区相同的是输出缓冲区也不会受到maxmemory的限制如果使用不当同样会造成maxmemory用满产生的数据丢失、键值淘汰、OOM等情况实际上输出缓冲区由两部分组成固定缓冲区16KB返回比较小的执行结果动态缓冲区返回比较大的结果。例如大的字符串、hgetall、smembers命令的结果等通过Redis源码中redis.h的redisClient结构体Redis3.2版本变为Client可以看到两个缓冲区的实现细节typedef struct redisClient {
// 动态缓冲区列表
list *reply;
// 动态缓冲区列表的长度(对象个数)
unsigned long reply_bytes;
// 固定缓冲区已经使用的字节数
int bufpos;
// 字节数组作为固定缓冲区
char buf[REDIS_REPLY_CHUNK_BYTES];
} redisClient;
固定缓冲区使用的是字节数组动态缓冲区使用的是列表。当固定缓冲区存满后会将Redis新的返回结果存放在动态缓冲区的队列中队列中的每个对象就是每个返回结果如下图所示obl、oll、omemclient list中的obl代表固定缓冲区的长度oll代表动态缓冲区列表的长度omem代表使用的字节数例如下面代表当前客户端的固定缓冲区的长度为0动态缓冲区有4869个对象两个部分共使用了133081288字节126M 内存id7 addr127.0.0.1:56358 fd6 name age91 idle0 flagsO db0 sub0 psub0 multi-1
qbuf0 qbuf-free0 obl0 oll4869 omem133081288 eventsrw cmdmonitor
监控输出缓冲区的方法依然有两种①通过定期执行client list命令收集obl、oll、omem找到异常的连接记录 并分析最终找到可能出问题的客户端②通过info命令的info clients模块找到输出缓冲区列表最大对象数例如(其中client_longest_output_list代表输出缓冲区列表最大对象数)这两种统计方法的优劣势和输入缓冲区是一样的这里就不再赘述了相比于输入缓冲区输出缓冲区出现异常的概率相对会比较大那么如何预防呢方法如下进行上述监控设置阀值超过阀值及时处理适当增大slave的输出缓冲区的如果master节点写入较大slave客户 端的输出缓冲区可能会比较大一旦slave客户端连接因为输出缓冲区溢出 被kill会造成复制重连限制容易让输出缓冲区增大的命令例如高并发下的monitor命令就 是一个危险的命令及时监控内存一旦发现内存抖动频繁可能就是输出缓冲区过大限制普通客户端输出缓冲区的把错误扼杀在摇篮中例如可以进行如下设置client-output-buffer-limit normal 20mb 10mb 120④客户端的存活状态age、idleclient list中的age和idle分别代表当前客户端已经连接的时间、最近一次的空闲时间例如下面这条记录代表当期客户端连接Redis的时间为304秒其中空闲了0秒例如下面这条记录代表当期客户端连接Redis的时间为8888581秒其中空闲了8888581秒。实际上这种就属于不太正常的情况当age等于idle时 说明连接一直处于空闲状态演示案例为了更加直观地描述age和idle下面用一个例子进行说明String key hello;
// 1) 生成jedis并执行get操作
Jedis jedis new Jedis(127.0.0.1, 6379);
System.out.println(jedis.get(key));
// 2) 休息10秒
TimeUnit.SECONDS.sleep(10);
// 3) 执行新的操作ping
System.out.println(jedis.ping());
// 4) 休息5秒
TimeUnit.SECONDS.sleep(5);
// 5) 关闭jedis连接
jedis.close();
下面对代码中的每一步进行分析用client list命令来观察age和idle参数的相应变化备注为了与redis-cli的客户端区分本次测试客户端IP地址10.7.40.981)在执行代码之前client list只有一个客户端也就是当前的rediscli下面为了节省篇幅忽略掉这个客户端。2)使用Jedis生成了一个新的连接并执行get操作可以看到IP地址为 10.7.40.98的客户端最后执行的命令是getage和idle分别是1秒和0秒3)休息10秒此时Jedis客户端并没有关闭所以age和idle一直在递 增4)执行新的操作ping发现执行后age依然在增加而idle从0计算也 就是不再闲置5)休息5秒观察age和idle增加6)关闭JedisJedis连接已经消失⑤客户端类型flagclient list中的flag是用于标识当前客户端的类型例如flagS代表当前客 户端是slave客户端、flagN代表当前是普通客户端flagO代表当前客户端 正在执行monitor命令。下图列出了11种客户端类型序号客户端类型说明lN普通客户端2M当前客户端是master节点3s当前客户端是slave节点4o当前客户端正在执行monitor命令5x当前客户端正在执行事务6b当前客户端正在等得阻塞事件7i当前客户端正在等待VM IO但是此状态目前已经废弃不用8d一个受监视的键已被修改EXEC命令将失敷9u客户端未被阻察10c回复完整输出后关闭连接11A尽可能快地关闭连接 二、client setName和client getNameclient setName xxclient setNameclient setName用于给客户端设置名字这样比较容易标识出客户端的来源。例如将当前客户端命名为test_client可以执行如下操作此时再执行client list命令就可以看到当前客户端的name属性为test_clientclient getNameclient getName如果想直接查看当前客户端的name可以使用client getName命令第一次进入客户端时客户端是没有名字的因此名字为空更改名字之后就可以看到更改后的名字了。例如client getName和setName命令可以做为标识客户端来源的一种方式但是通常来讲在Redis只有一个应用方使用的情况下IP和端口作为标识会更加清晰。当多个应用方共同使用一个Redis那么此时client setName可以作为标识客户端的一个依据三、client killclient kill ip:port此命令用于杀掉指定IP地址和端口的客户端由于一些原因例如设置timeout0时产生的长时间idle的客户端需要手动杀掉客户端连接时可以使用client kill命令演示案例例如左侧为一个客户端127.0.0.1:34658右侧为一个客户端127.0.0.1:34660如果想杀掉127.0.0.134656的客户端可以执行执行命令后client list结果只剩下了127.0.0.1:34658自己这个客户端四、client pauseclient pause timeout(毫秒)client pause命令用于阻塞客户端timeout毫秒数在此期间客户端连接将被阻塞。如下图所示演示案例例如在一个客户端执行下面的命令在之后的10000毫秒内的其他客户端连接都会被阻塞过一会后在另一个客户端执行ping命令发现整个ping命令执行了2.40秒手动执行redis-cli只为了演示不代表真实执行时间该命令可以在如下场景起到作用client pause只对普通和发布订阅客户端有效对于主从复制从节点内部伪装了一个客户端是无效的也就是此期间主从复制是正常进行的 所以此命令可以用来让主从复制保持一致client pause可以用一种可控的方式将客户端连接从一个Redis节点切换到另一个Redis节点需要注意的是在生产环境中暂停客户端成本非常高五、monitormonitor命令用于监控Redis正在执行的命令 演示案例如下图所示我们打开了两个redis-cli右侧先执行monitor命令左侧再执行其他命令可以看到monitor命令能够监听其他客户端正在执行的命令并记录了详细的时间戳注意事项monitor的作用很明显如果开发和运维人员想监听Redis正在执行的命令就可以用monitor命令但事实并非如此美好每个客户端都有自己的输出缓冲区既然monitor能监听到所有的命令一旦Redis的并发量过大 monitor客户端的输出缓冲会暴涨可能瞬间会占用大量内存。