Redis 客户端使用与监控

原创
2017/09/13 12:39
阅读数 6K

 

1、客户端通信协议

1)客户端与服务端之间的同学协议是在TCP协议之上构建的;

2)Redis定制了RESP(Redis Serialization Protocol ,Redis 序列化协议)实现客户端与服务端的正常交互。正因为这种协议简单而又容易理解,所以很多编程语言的客户端就容易实现了,比如 Java的客户端 Jedis.

 

2、客户端Jedis的使用

生产环境一般我们不会使用直连的方式(因为连接没法管理,导致资源不可控),而是使用连接池,使用 Jedis 连接池时主要注意一下几个方面。

1)maxActive:最大连接数,默认8个,生产环境一般配置16个差不多,(主要是Jedis处理高效)

2)maxIdle:池子里的最大空闲连接数,默认8个,意思是没有客户端来连接时池里最多闲置 8 个

3)minIdle:池子里的最小空闲连接数,默认0,意思是没有客户端来连接时池里最少闲置数

4)jmxEnabled:是否开启jmx监控,默认为 true,可以通过 jconsole 等工具监控连接池

5)minEvictableIdleTimeMillis:连接最小空闲时间,默认30分钟,达到这个值后空闲连接被移除

6)numTestsPerEvictionRun:做空闲连接检测时每次采样数,默认 3

7)TestOnBorrow:向连接池借用连接时是否做连接的有效性检测(Ping),默认false,如果设置为true,那么每次借用时都会多一次 ping,不过增强了代码的健壮性,其实如果是在Redis服务端配置了 timeout ,那么这个操作我觉得是很有必要的,因为服务端会把你这边的连接给移除。

8)testOnReturn:同上,不过这里是归还时,默认为false。

9)testWhileIdle:对连接池的连接时是否做空闲检测,默认为 false

10)timeBetweenEvicationRunsMillis:空闲连接检测周期,单位为毫秒,默认 -1 ,不做检测

11)blockWhenExhausted:当连接池用尽后,新的调用者是否要等待空闲连接,这个参数和下面的maxWaitMillis 对应的,只有当 blockWhenExhausted = true 时 maxWaitMillis 才会生效。默认为 true。

12)maxWaitMillis:当连接池资源用尽后,新的调用者来等待空闲连接时的最大时间,单位毫秒,默认 -1 ,表示永不超时,这个很要命的,一定要改掉。

 

3、客户端管理

1)查看客户端连接情况

>info clients

# Clients

connected_clients:2 // 当前连接数,这个暴增,说明连接池没有配置得当

client_longest_output_list:0 // 输出缓冲区列表最大对象数,其实就是最大 oll

client_biggest_input_buf:0 // 最大输入缓冲区,单位字节,其实就是最大 qbuf

blocked_clients:0 // 正在阻塞阻塞命令(比如 blpop brpop 等)的客户端个数

 

2)查看服务端连接汇总

> info stats

# Stats

total_connections_received:6 // 从启动到现在连接的总数(并不是当前连接数)

rejected_connections:0 // 从启动到现在拒绝的连接数

 

3)查看客户端连接的详细信息

>client list

id=5 addr=127.0.0.1:52821 fd=8 name= age=115 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client

 

id=6 addr=127.0.0.1:52822 fd=9 name= age=91 idle=10 flags=O db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=monitor

 

id:唯一标识

name:客户端名称,通过 client setName client1 和 client getName 来设置获取名称

addr : 客户端的地址和端口,当想停止该客户端时则可以通过这个值 kill 掉

fd : 套接字所使用的文件描述符,Linux 里的 socket 句柄

age : 以秒计算的已连接时长,表示 client 从连接到现在的时长,所以叫做年龄

idle : 以秒计算的空闲时长,表示当前距离上一次执行命令的空闲时长

flags : 客户端 flag,标识客户端的信息,比如主从服务,事务执行情况等

db : 该客户端正在使用的数据库 ID

sub : 已订阅频道的数量

psub : 已订阅模式的数量

multi : 在事务中被执行的命令数量,如果没有使用事务就是 -1,记住是命令个数,包括读写

qbuf : 查询缓冲区的长度(字节为单位, 0 表示没有分配查询缓冲区)

qbuf-free : 查询缓冲区剩余空间的长度(字节为单位, 0 表示没有剩余空间)

obl : 输出缓冲区的长度(字节为单位, 0 表示没有分配输出缓冲区)

oll : 输出列表包含的对象数量(当输出缓冲区没有剩余空间时,命令回复会以字符串对象的形式被入队到这个队列里)

omem : 输出缓冲区和输出列表占用的内存总量

events : 文件描述符事件,w 可写, r 可读

cmd : 最近一次执行的命令

 

注意:

A:输入缓冲区 qbuf 和 qbuf-free 以及 client_biggest_input_buf

Redis为每个客户端分配了输入缓冲区,它的作用是将客户端发送的命令临时保存,同时Redis会从输入缓冲区拉取命令并执行。其中 qbuf 代表这个缓冲区的总容量,qbuf-free 代表剩余容量。

Redis并没有提供相应的配置来规定每个缓冲区的大小,输入缓冲区会根据输入的内容大小的不同动态调整,只是要求每个客户端缓冲区的大小不能超过1G,超过后客户端将被关闭;另外如果没有达到 1 G,但是和当前Redis的空间加起来已经超过 MaxMemory 时,也可能出现 OOM,这个时候命令可能会被丢失。

其实生产环境很少有因为输入缓冲区导致的阻塞,主要还是因为命令过多积累在执行队列中,因此我们可以通过 qbuf 预测出这个连接有多少命令被发送,如果真的 qbuf 非常大,那么命令太多,可能会导致阻塞,比如管道、事务命令等。当然也有可能服务端发生阻塞导致客户端的命令一直被积压,也有可能客户端执行了大对象。

 

B:输出缓冲区 obl 和 oll 以及 client_longest_output_list

Redis为每个客户端分配了输出缓冲区,它的作用是保存命令执行的结果返回给客户端,其实就是为命令返回结果提供临时缓冲区。

与输入缓冲区不同的是,输出缓冲区的大小可以通过 client-output-buffer-limit 来进行设置。

输出缓冲区有两部分组成,固定缓冲区(obl)和动态缓冲区(oll),固定缓冲区只有 16KB,也就是返回值大于 16KB时,就会动用固定缓冲区,两种计算方式不一样哦,固定缓冲区是用字节单位,动态缓冲区使用 对象个数。另外 omem 是指动态缓冲区+固定缓冲区的总字节数。

生产环境遇到的问题在输出缓冲区还是比较多的,比如大对象的获取,就会造成 oll 占用过大,从而导致阻塞,所以最好是限制住 client-output-buffer-limit ,然后报警提示。

 

 

4)设置最大连接数 maxClients

> config get maxClients

1) "maxclients"

2) "10000"

> config set maxClients 500

OK

// 最大连接数 10000,然而 Jedis的连接数默认是 8 ,对比一下差距好大啊,不知道这里如何设置的,是不是考虑到集群等因素。

 

5)设置检测客户空闲时间

> config get timeout

1) "timeout"

2) "30"

> config get timeout

1) "timeout"

2) "45"

// 如果client的idle得到了45,那么这个连接就会被kill掉,所以使用连接池时最好对连接进行可用性检测,同时也要避免客户端在一个连接内消耗大量的时间。

 

6)client setName | getName

> client setName client1

OK

> client getName

"client1"

// 给客户端指定一个自定义名字,方便查找。 我们可以在 client list 找到。

或者执行 > redis-cli client list | grep client1

 

7)client kill addr

>client kill 127.0.0.1:52875

>OK

 

8)client pause timeout(毫秒)

>client pause 1000

// 阻塞客户端 1000 毫秒,要知道Redis是单线程的,如果这个客户端阻塞,那么其他客户端全部都要等待他执行完成,所以一切客户端导致的延迟阻塞,都会是服务端的延迟阻塞。

 

 

9)monitor 监控其他客户端的命令执行

> monitor

OK

1503724607.774500 [0 127.0.0.1:52880] "get" "str"

1503724610.339557 [0 127.0.0.1:52880] "set" "str" "hll"

// 在寻找问题时这个命令很管用,但是高并发下,这个命令很致命的,因为大量输出导致该客户端的输出缓冲区被占满,从阻塞输出。所以用过后尽早关闭。

第一个是执行命令的时间戳,可以使用 new Date(1503724607.774*1000)

第二个时数据库索引 0

第三个是执行的命令以及命令的参数 "get" "str"

 

 

10)客户端的其他配置

1)timeout :指Redis的连接如果空闲时间超过timeout则断开,可以通过 client list 查看连接

2)maxClients:这个和下面的 tcp 连接数不是一码事,这个指的是客户端数。

3)tcp-keepalive:检测TCP连接的活性周期,默认为 0 ,不检测。这个最好是配置一个 60 秒,因为大量的死连接会占用服务端的TCP资源。

4)tcp-backlog:TCP 三次握手成功后,会把这个连接放入队列中,这个队列的最大长度就是 tcp-backlog 的配置,默认是 511 , 通常这个参数不用调整。但是有些Linux系统的这个值配置时 128,则需要对应调整为 511.

如下查看和设置

> cat /proc/sys/net/core/somaxconn

128

> echo 511 > /proc/sys/net/core/somaxconn

> cat /proc/sys/net/core/somaxconn

511

 

展开阅读全文
打赏
1
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
1
分享
返回顶部
顶部