Redis定位问题常用命令总结

redis客户端分析


在redis出现故障时,很有可能是redis客户端没有合理使用redis,出现疯狂建立redis连接或者写入大量的数据到redis导致的,在这种情况下我们必须要找到有问题的客户端才能找到故障的触发点。

1.client list

使用命令行登录redis后,输入client list命令可以列出所有与redis服务端相连的客户端连接信息,输出的每一行代表一个客户端,下面对一些重要的属性进行介绍:

id=81548 addr=10.5.4.137:38296 fd=501 name= age=1849 idle=2 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=hget
id=81877 addr=10.5.5.30:55960 fd=102 name= age=69 idle=20 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping
  • 客户端标志:id、addr、fd、name
    id: 客户端的唯一标志,随redis的连接自增,重启redis后置为0。
    addr:客户端的ip和端口,通过此项可以排查是否有其他异常客户端在连接redis
    fd:socket文件描述符,与lsof命令结果中的fd是同一个
    name:客户端的名字,gde场景下为空。
  • 输入缓冲区:qbuf、qbuf-free
    输入缓冲区是redis用来缓存客户端发来的命令的,qbuf和qbug-free分布代表这个缓冲区的总容量和剩余容量。redis会根据输入内容的大小自动调节输入缓冲区的大小;目前redis没有配置可以修改输入缓冲区的大小,只是限制单个客户端最多只能使用1G。
    输入缓存区分配不当会导致两个问题:
    1.某个客户端的输入缓冲区超过1G,该客户端将被关闭;
    2.输入缓冲去不受maxmemory控制,如果redis已存的数据加上输入缓冲区大小超过了mmaxmemory,可能会导致数据丢失、键值淘汰、OOM等情况。
    输入缓存区使用不当一般是两个原因造成的:
    1.redis的处理速度跟不上输入缓冲去的输入速度,并且每次进入输入缓冲的的命令包含大量的bigkey,从而导致输入缓冲区过大;
    2.redis发生了阻塞,短时间内不能处理命令,造成客户端输入的命令还积压在输入缓冲区里面。
    通过执行client list收集qbuf和qbuf-free找到异常的连接并分析,就能找到可能出问题的redis客户端。
    同样通过info clients查看里面的client_biggest_input_buf同样可以发现缓冲区异常的情况。
127.0.0.1:6379> info clients
\# Clients
connected_clients:1414
client_longest_output_list:0
client_biggest_input_buf:209715200
blocked_clients:0
  • 输出缓冲区:obl、oll、omem
    输出缓冲区作用是保存命令执行的结果,为redis与客户端交互提供缓冲。按照客户端的不同,输出缓冲区有3中,分别是普通客户端,发布订阅客户端和slave客户端。
# client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>
# <class> 客户端类型
# <hard limit> 客户端使用的缓冲区超过这个限制会被立刻关闭
# <soft limit> <soft seconds> 客户端使用的缓冲区超过<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

redis的输出缓冲区包括静态缓冲区和动态缓冲区,静态缓冲区是用数组存放数据,主要用以存放较小的结果;动态缓冲区使用链表存储数据,主要是存放较大的结果,链表中每个对象就是一个结果。obl就是静态缓冲区,oll就是动态缓冲区,omem就是该客户端所使用的所有的字节数。
redis输出缓冲区也不会受到maxmemory限制,使用不当也会导致OOM等故障。
通过info clients同样可以得到输出缓冲区列表的最大数量,如下client_longest_output_list就是:

127.0.0.1:6379> info clients
# Clients
connected_clients:502
client_longest_output_list:4869
client_biggest_input_buf:0
blocked_clients:0

【输出缓冲区的推荐配置】

1.限制普通客户端输出缓冲区的大小。
client-output-buffer-limit normal 100mb 10mb 120
2.适当增大slave的输出缓冲区的,如果master节点写入较大,slave客户
端的输出缓冲区可能会比较大。
3.及时监控内存,一旦发现内存抖动频繁,可能就是输出缓冲区过大。
4.监控client list和info clients的结果,设置阀值,超过阀值及时处理。
  • 客户端类型:flag
    flag用来标记客户端类型和状态,重要的状态如下表格所示:
序号客户端类型说明
1N普通客户端
2b当前客户端正在等待阻塞事件
3x当前客户端正在执行事务
4O当前客户端正在执行Monitor命令
5M当前客户端是master节点
6S当前客户端是slave节点
7u客户端未被阻塞
8c回复完整输出后,客户端将被关闭
9A尽可能快的额关闭连接
2. client kill

此命令可以杀掉指定ip和端口的客户端,在找到问题客户端后,可以通过此命令快速杀掉客户端,规避问题。

127.0.0.1:6379> client kill 127.0.0.1:52343
OK
3. client pause

阻塞客户端timeout毫秒数,只对平台客户端和发布订阅客户端有效果,对于slave客户端不起作用,在此期间主从复制是正常执行的。

client pause timeout(毫秒)

client pause给运维提供了一种可控的操作窗口期,但是暂停客户端成本较高,生产环境慎用。

4. monitor

该命令用于监控redis正在执行的命令,并且有时间戳;monitor需要用到客户端输出缓冲区,有可能导致redis OOM故障,生产环境慎用。

5. info clients

info clients获取客户端的一些统计信息

127.0.0.1:6379> info clients
# Clients
connected_clients:1414              #当前redis客户端的连接数
client_longest_output_list:0        #当前所有输出缓冲区中对象个数的最大值
client_biggest_input_buf:2097152    #当前所有输入缓冲区所占字符的最大值
blocked_clients:0                   #正在执行阻塞命令的客户端数量

此外info stats命令也可以输出一些客户端的信息

127.0.0.1:6379> info stats
# Stats
total_connections_received:25472        #redis启动以来连接的客户端总数
total_commands_processed:9911355
instantaneous_ops_per_sec:0
rejected_connections:0           #redis启动以来拒绝的客户端连接总数,需要重点关注
sync_full:0
sync_partial_ok:0
sync_partial_err:0
expired_keys:31843
evicted_keys:0
keyspace_hits:2536514
keyspace_misses:28160
pubsub_channels:0
pubsub_patterns:0
latest_fork_usec:675
6. slowlog 慢查询

# 设置redis慢查询阈值,通过配置文件也可行
127.0.0.1:6379> config set slowlog-log-slower-than 20000
OK

# 获取redis慢查询阈值
127.0.0.1:6379> config get slowlog-log-slower-than
1) "slowlog-log-slower-than"
2) "10000" (微妙)

# 设置redis慢查询队列长度,通过配置文件也可行
127.0.0.1:6379> config set slowlog-max-len 1000
OK

# 获取redis慢查询队列长度
127.0.0.1:6379> config get slowlog-max-len
1) "slowlog-max-len"
2) "1000"

# 获取前2个慢查询
127.0.0.1:6379> slowlog get 2
1) 1) (integer) 14              # 唯一标志
   2) (integer) 1617157879      # 时间戳
   3) (integer) 11              # 耗时
   4) 1) "set"                  # 命令
      2) "mykey"                # 参数
      3) "myvalue"              # 参数
2) 1) (integer) 11
   2) (integer) 1617157861
   3) (integer) 30
   4) 1) "keys"
      2) "*"

# 当前慢查询的队列长度
127.0.0.1:6379> slowlog len
(integer) 17

# 清理慢查询日志
127.0.0.1:6379> slowlog reset
OK

【最佳实践】

参数推荐设置
slowlog-max-len建议线程调大查询列表,可以设置为1000以上,减少命令被挤出队列的可能;redis会对长命令做截断,不用担心占用内存。
·slowlog-log-slower-than需要根据业务场景进行评估,由于redis是单线程处理请求,例如需要500的tps,那么每条命令的执行时候不能超过2ms,所以需要设置为20微妙以下
7. redis-cli
  • –bigkeys 使用scan对Redis的键进行采样,从中找到内存占比较大的键值;实际使用感觉对于单个string能找到比较大的对象,但是对于集合里面的超大key,是不容易找到问题key的。
  • –latency 测试客户端到目标redis的网络延迟。
  • –latency-history 分时段形式采样网络延迟。
  • –stat 看到redis的一些增量信息,如客户端、请求量等信息。
  • –eval 执行制定的lua脚本。
  • –slave 把当前客户端模拟成redis的从节点,可以用来获取redis的更新操作。
  • –rdb 请求redis生成rdb持久化文件。
  • –r n 重复执行命令n次
  • –i m 每隔m秒执行一次命令
reids内存陡增分析
Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐