Redis 服务器管理相关命令

来源:
三产
最后修订:
2017年06月29日 09:13:51
 220

客户端相关

查看客户端列表

CLIENT LIST

自2.4.0可用。

时间复杂度:O(N) N是客户端连接数量。

语法:CLIENT LIST
说明:

Redis CLIENT LIST 命令用于返回所有连接到服务器的客户端信息和统计数据。

返回值:

一...

客户端相关

查看客户端列表

CLIENT LIST

自2.4.0可用。

时间复杂度:O(N) N是客户端连接数量。

语法:CLIENT LIST
说明:

Redis CLIENT LIST 命令用于返回所有连接到服务器的客户端信息和统计数据。

返回值:

一个独特的字符串,格式如下:

  • 每个已连接客户端对应一行(以 LF 分割)
  • 每行字符串由一系列 属性=值(property=value) 形式的域组成,每个域之间以空格分开。

下面是各字段的含义:

  1. 客户端标识

    CLIENT LIST 命令中相关字段:

  2. id: 唯一的64位的客户端1ID(Redis 2.8.12加入)。

  3. addr: 客户端的地址和端口

  4. fd: 套接字所使用的文件描述符

  5. name:客户端的名字,后面的 CLIENT SETNAMECLIENT GETNAME 两个命令会对其进行说明。

  6. 输入缓冲区

    Redis 为每个客户端分配有输入缓存区,用于将客户端发送的命令临时保存。Redis 会从缓存区中拉取命令并执行。输入缓冲区会根据输入内容大小的不同动态调整,只是要求每个客户端缓冲区的大小不能超过 1G ,超过后客户端将被关闭。

    输入缓冲区不受 maxmemory 控制,假设一个 Redis 实例设置了 maxmemory 为4G,已经存储了2G数据,但是如果此时输入缓冲区使用了 3G,已经超过 maxmemory 限制,可能会产生数据丢失、键值淘汰、Out Of Memory 等情况。这种情况在正常使用过程中出现较少,但是需要注意防范 Redis 使用不规范导致出现这种情况

    造成缓冲区过大的原因是 输入命令过多,Redis 无法及时处理,可能的情况:

    ​ a) 客户端过多,命令输入过多。

    ​ b) 由于命令使用的不恰当(key过大,或运行时间复杂度较高的命令)等原因造成 Redis 阻塞无法处理新的命令,从而导致客户端输入的命令积压在输入缓冲区,造成了输入缓冲区过大。

    监控输入缓冲区异常的方法有两种: a) 通过定期执行 CLIENT LIST 命令,收集 qbufqbuf-free 找到异常的连接记录并分析,最终找到可能出问题的客户端。该方法可以精准的监控每个客户端,但执行较慢,在连接数较多时可能会阻塞 Redis。 b) 通过 INFO CLIENTS 命令,找到最大的输入缓冲区(client_biggest_input_buf),该命令相较于 CLIENT LIST 执行较快,结果一目了然,但无法精准到具体客户端,无法查看缓存区大小等信息。

    CLIENT LIST 命令中相关字段:

  7. qbuf: 查询缓冲区的总容量(字节为单位, 0 表示没有分配查询缓冲区)

  8. qbuf-free: 查询缓冲区剩余容量(字节为单位, 0 表示没有剩余空间)

  9. 输出缓冲区

    Redis为每个客户端分配了输出缓冲区,它的作用是保存命令执行的结果返回给客户端,为Redis和客户端交互返回结果提供缓冲。与输入缓冲区不同的是,输出缓冲区的容量可以通过参数 client-outputbuffer-limit 来进行设置,并且输出缓冲区做得更加细致,按照客户端的不同分为三种:普通客户端、发布订阅客户端、slave客户端,不同类型的客户端的输出缓冲区不同可以分别进行设置。

    在 Redis 配置文件中可以配置:

    client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>

    其中:

  10. <class> :客户端类型,分为三种。

    a)normal:普通客户端;

    b)slave:slave客户端,用于复制;

    c)pubsub:发布订阅客户端。

  11. <hard limit>:如果客户端使用的输出缓冲区大于<hard limit>,客户端会被立即关闭。

  12. <soft limit><soft seconds> :如果客户端使用的输出缓冲区超过了 <soft limit> 并且持续了 <soft limit> 秒,客户端会被立即关闭。

    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
    

    输出缓冲区同样存在内存溢出的问题。(见 输入缓冲区相关内容)

    输出缓冲区由两部分组成:响应缓冲区(16KB)和回复列表,其中响应缓冲区返回比较小的执行结果,而回复列表返回比较大的结果,例如大的字符串、HGEtALLSMEMBERS 命令的结果等。

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

    监控输出缓冲区异常的方法有两种: a) 通过定期执行 CLIENT LIST 命令,收集 oblollomem 找到异常的连接记录并分析,最终找到可能出问题的客户端。该方法可以精准的监控每个客户端,但执行较慢,在连接数较多时可能会阻塞 Redis。 b) 通过 INFO CLIENTS 命令,找到最大的回复列表(client_longest_output_list),该命令相较于 CLIENT LIST 执行较快,结果一目了然,但无法精准到具体客户端,无法查看缓存区大小等信息。

    相比于输入缓冲区,输出缓冲区出现异常的概率相对会比较大,预防出现问题的方法:

  13. 通过上面两中方法进行监控,设置阈值,超阈值后及时处理。

  14. 显示普通客户端的输出缓存区:

    client-output-buffer-limit normal 20mb 10mb 120

  15. 适当增大 slave 的输出缓冲区的,如果 master 节点写入较大,slave 客户端的输出缓冲区可能会比较大,一旦 slave 客户端连接因为输出缓冲区溢出被 kill ,会造成复制重连。

  16. 限制容易让输出缓冲区增大的命令,例如,高并发下的 MONITOR 命令就是一个危险的命令。

  17. 及时监控内存,一旦发现内存抖动频繁,可能就是输出缓冲区过大。

    CLIENT LIST 命令中相关字段:

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

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

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

  21. 客户端的存活状态

  22. age: 以秒计算的已连接时长

  23. idle: 最近一次(100ms 或者更长时间)以秒计算的空闲时长

  24. 客户端类型

  25. flags: 客户端 flag

    客户端 flag 可以由以下部分组成:

    • O: 客户端是 MONITOR 模式下的附属节点(slave)
    • S: 客户端是一般模式下(normal)的附属节点
    • M: 客户端是主节点(master)
    • x: 客户端正在执行事务
    • b: 客户端正在等待阻塞事件
    • i: 客户端正在等待 VM I/O 操作(已废弃)
    • d: 一个受监视(watched)的键已被修改, EXEC 命令将失败
    • c: 在将回复完整地写出之后,关闭链接
    • u: 客户端未被阻塞(unblocked)
    • U: 通过Unix套接字连接的客户端
    • r: 客户端是只读模式的集群节点
    • A: 尽可能快地关闭连接
    • N: 未设置任何 flag,普通客户端
  26. db: 该客户端正在使用的数据库 ID

  27. sub: 已订阅频道的数量

  28. psub: 已订阅模式的数量

  29. multi: 在事务中被执行的命令数量

  30. events: 文件描述符事件

  31. cmd: 最近一次执行的命令

文件描述符事件可以是:

  • r: 客户端套接字(在事件 loop 中)是可读的(readable)
  • w: 客户端套接字(在事件 loop 中)是可写的(writeable)

为了 debug 的需要,经常会对域进行添加和删除。一个版本安全的 Redis 客户端使用这个命令时应该根据字段解析相应内容。(比如:处理未知的字段,应跳过该字段)。

示例:
coderknock> CLIENT LIST
# 连接时间 87 秒 空闲 87 秒 说明该连接一直处于空闲状态
id=3 addr=127.0.0.1:55773 fd=8 name= age=87 idle=87 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=18446744073709537584 events=r cmd=command
id=4 addr=127.0.0.1:55795 fd=7 name= age=58 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=18446744073709537584 events=r cmd=client
#响应缓冲区的长度为0,回复列表有4869个对象,两个部分共使用了133081288字节=126M
id=7 addr=127.0.0.1:56358 fd=6 name= age=91 idle=0 flags=O db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=4869 omem=133081288 events=rw cmd=monitor

获取/设置名称

CLIENT GETNAME

自2.6.9可用。

时间复杂度:O(1)。

语法:CLIENT GETNAME
说明:

CLIENT GETNAME 返回当前连接由CLIENT SETNAME设置的名字。如果没有用CLIENT SETNAME设置名字,将返回一个空的回复。

返回值:

返回连接名字或者空(没有设置名字时)

示例:
coderknock> CLIENT GETNAME
(nil)
# 只针对当前客户端
coderknock> CLIENT SETNAME coderknock
OK
coderknock> CLIENT GETNAME
"coderknock"

CLIENT SETNAME

自2.6.9可用。

时间复杂度:O(1)。

语法:CLIENT SETNAME connection-name
说明:

为当前连接分配一个名字。

这个名字会显示在 CLIENT LIST 命令的结果中, 用于识别当前正在与服务器进行连接的客户端。

举个例子, 在使用 Redis 构建队列(queue)时, 可以根据连接负责的任务(role), 为信息生产者(producer)和信息消费者(consumer)分别设置不同的名字。

名字使用 Redis 的字符串类型来保存, 最大可以占用 512 MB 。 另外, 为了避免和 CLIENT LIST 命令的输出格式发生冲突, 名字里不允许使用空格。

要移除一个连接的名字, 可以将连接的名字设为空字符串 ""

使用 CLIENT GETNAME 命令可以取出连接的名字。

新创建的连接默认是没有名字的。

在 Redis 应用程序发生连接泄漏时,为连接设置名字是一种很好的 debug 手段。

返回值:

设置成功时返回 OK

示例:
 # 新连接默认没有名字

coderknock> CLIENT GETNAME
(nil)

# 设置名字
coderknock> CLIENT SETNAME coderknock
OK

# 返回名字
coderknock> CLIENT GETNAME
"coderknock"

# 在客户端列表中查看
coderknock> CLIENT LIST
id=5 addr=127.0.0.1:49298 fd=8 name=coderknock age=173 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=18446744073709537584 events=r cmd=client

# 清除名字
coderknock> CLIENT SETNAME        # 只用空格是不行的!
(error) ERR Syntax error, try CLIENT (LIST | KILL ip:port)
coderknock> CLIENT SETNAME ""     # 必须双引号显示包围
OK
coderknock> CLIENT GETNAME
(nil)
coderknock> CLIENT LIST
id=5 addr=127.0.0.1:49298 fd=8 name= age=203 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=18446744073709537584 events=r cmd=client

#别的客户端同样可以取名为 coderknock
coderknock> CLIENT LIST
id=6 addr=127.0.0.1:49438 fd=7 name=coderknock age=67 idle=32 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=18446744073709537584 events=r cmd=client
id=7 addr=127.0.0.1:49454 fd=9 name=coderknock age=25 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=18446744073709537584 events=r cmd=client

在 Redis 只有一个应用方使用的情况下,IP和端口作为标识会更加清晰。当多个应用方共同使用一个Redis,那么此时 CLIENT SETNAME 可以作为标识客户端的一个依据。

客户端限制

maxclients timeout

在之前的 《Redis 配置》一文中我们讲过 CONFIG GET CONFIG_SETTING_NAMECONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE,命令,其中CONFIG GET/SET maxclients 用于获取/设置客户端最大连接数,一旦连接数超过 maxclients 新的连接将被拒绝,maxclients 默认值是10000,可以通过 INFO clients来查询当前Redis的连接数:

# 查询最大连接数
coderknock> CONFIG GET maxclients
1) "maxclients"
2) "10000"
coderknock> INFO clients
# Clients
connected_clients:1 #当前连接客户端数
client_longest_output_list:0
client_biggest_input_buf:0
blocked_clients:0

可以通过 CONFIG SET maxclients 对最大客户端连接数进行动态设置:

# 我们将 maxclients 设置小些
coderknock> CONFIG SET maxclients 2
OK
coderknock> CONFIG GET maxclients
1) "maxclients"
2) "2"
# 我们启动再启动两个客户端此时在第一个或第二个客户端上执行
coderknock> CLIENT LIST
id=2 addr=127.0.0.1:51010 fd=7 name= age=386 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=18446744073709537584 events=r cmd=client
id=3 addr=127.0.0.1:51091 fd=8 name= age=154 idle=126 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=18446744073709537584 events=r cmd=keys
# 在第三个启动的客户端上进行操作(命令窗口并没有关闭所以还是可以执行的)
coderknock> keys *
Error: 远程主机强迫关闭了一个现有的连接。
# 可以看到这个客户端不能正常使用

一般情况下 maxclients 默认的 10000 大小已经做够使用了,但是有时由于使用不当可能导致存在大量空闲连接(idle 较大的连接),无论是从网络连接的成本还是超过maxclients的后果来说都不是什么好事,因此 Redis 提供了 timeout (单位为秒)参数限制连接的最大空闲时间,一旦客户端空闲时间超过了 timeout 设置,连接将会被关闭。使用 CONFIG GET/SET timeout 可以获取设置 timeout:

# #Redis默认的 timeout 是0,也就是没有超时时间
coderknock> CONFIG GET timeout
1) "timeout"
2) "0"

Redis的默认配置给出的 timeout=0 ,在这种情况下客户端基本不会出现上面的异常,这是基于对客户端开发的一种保护。如果客户端设置了超时,可能就会出现连接超时的异常,对应用业务造成一定影响,但是如果 Redis 的客户端使用不当或者客户端本身的一些问题,造成没有及时释放客户端连接,可能会造成大量的空闲连接占据着很多连接资源,一旦超过 maxclients;后果也是不堪设想。所在在实际开发和运维中,需要将 timeout 设置成大于0 且较大的数字,例如可以设置为300秒,同时在客户端使用上添加空闲检测和验证等等措施。

关闭客户端

CLINET KILL

自2.4.0可用。

时间复杂度:O(N) N是客户端连接数量。

语法:CLIENT KILL [ip:port][ID client-id] [normal|slave|pubsub][ADDR ip:port][SKIPME yes/no]
说明:

CLIENT KILL关闭一个指定的连接。在 Redis2.8.11 时可以根据客户端地址关闭指定连接,关闭方式如下:

CLIENT KILL addr:port addr:port 应该是 CLIENT LIST 命令里面列出的客户端连接之一。

然而,从Redis 2.8.12开始,这个命令改为如下格式:

CLIENT KILL <filter> <value> ... ... <filter> <value>

新的格式可以根据不同属性杀死客户端而不是只按地址杀死。他们有以下一些格式:

  • CLIENT KILL ADDR ip:port : 和旧版的三个参数时的行为完全一样。
  • CLIENT KILL ID client-id : 可以通过唯一 ID 字段杀死一个客户端,唯一 ID 可以通过 Redis 2.8.12 开始的 CLIENT LIST 命令查询(之前版本可能没有 ID 字段)。
  • CLIENT KILL TYPE type : 这里的 type 可以是 normal, slave, pubsub (Redis 3.2 版本之后增加了 master 类型的支持)。 这将关闭所有特殊类的客户端。 请注意被认为是属于正常类的客户端将会被MONITOR 命令监视到。
  • CLIENT KILL SKIPME yes/no:默认情况下,该选项设置为yes ,即调用过该命令的客户端将不会被杀死,将该选项设置为 no 即也会杀死调用过该命令的客户端。

该命令支持同时使用多个过滤器,或杀死多个过滤器的合集。

由于Redis的单线程特性,在执行命令时无法终止客户端连接。从客户端的角度来看,在执行命令的过程中,连接永远不会被关闭。但是,只有当下一个命令发送(并导致网络错误)时,客户端才会注意到连接已关闭。

返回值:

当用三个参数格式调用时:

如果连接存在并已关闭返回OK

当使用过滤器/值格式调用时:

客户端数量被杀。

示例:
# 列出所有已连接客户端

coderknock> CLIENT LIST
addr=127.0.0.1:43501 fd=5 age=10 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

# 杀死当前客户端的连接

coderknock> CLIENT KILL 127.0.0.1:43501
OK

# 之前的连接已经被关闭,CLI 客户端又重新建立了连接
# 之前的端口是 43501 ,现在是 43504

coderknock> CLIENT LIST
addr=127.0.0.1:43504 fd=5 age=0 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

由于一些原因(例如设置 timeout=0 时产生的长时间空闲的客户端),需要手动杀掉客户端连接时,可以使用 CLIENT KILL 命令。

阻塞客户端

CLIENT PAUSE

自2.9.5可用。

时间复杂度:O(1)。

语法:CLIENT PAUSE timeout
说明:

CLIENT PAUSE 是一个连接控制命令,可以在指定的时间(以毫秒为单位)中挂起所有Redis客户端。

该命令执行以下操作:

  • 只对普通和发布订阅客户端有效,对于主从复制(从节点内部伪装了一个客户端)是无效的,也就是此期间主从复制是正常进行的,所以此命令可以用来让主从复制保持一致。
  • 但是它尽可能地返回给调用者,因此 CLIENT PAUSE 命令的执行不会自动暂停(返回之后还是会暂停自身的客户端)。
  • 当指定的时间量过去时,所有客户端都被解除阻塞:这将在暂停期间触发对每个客户端的查询缓冲区中累积的所有命令的处理。

此命令非常有用,因为它可以用一种可控的方式将客户端连接从一个Redis节点切换到另一个Redis节点。例如,在实例升级期间,系统管理员可以执行以下操作:

  • 使用 CLIENT PAUSE 暂停客户
  • 等待几秒钟以确保从站从主设备处理最新的复制流。
  • 把一个从节点变成一个主节点。
  • 重新配置客户端以连接新的主节点。

可以将命令 暂停 发送到 MULTI / EXEC 块 INFO replication 中,以便在客户端被阻止时获取当前的主节点偏移量。这样,可以在从属端等待特定的偏移量,以确保处理所有的复制流。

Redis 3.2.10 / 4.0.0 中此命令还可以防止在客户端暂停期间键被释放或过期。这样,数据集就被保证是静态的,而不仅仅是从客户端无法写入的角度来看,而且从内部操作的角度来说也是如此。

返回值:

如果超时无效,则该命令返回OK或错误。

示例:
coderknock> CLIENT PAUSE 10000
OK
coderknock> GET hello
"world"
(10.06s) # 这里可以看到查询花费 10s 的时间

该命令在生产环境如要使用应挑选操作较少时,不然可能会引发不可预知的情况。

客户端回复设定

CLIENT REPLY

自3.2.0可用。

时间复杂度:O(1)。

语法:CLIENT REPLY ON|OFF|SKIP
说明:

有时客户端可以完全禁用Redis服务器的回复

CLIENT REPLY 命令控制服务器是否会回复客户端的命令。提供以下模式:

  • ON。这是默认模式服务器返回每个命令的回复。
  • OFF。在此模式下,服务器将不会回复客户端命令。
  • SKIP。此模式会立即跳过命令的回复。
返回值:

当用 OFFSKIP 命令调用时,不作任何回复。调用时ON:返回OK

该命令是新命令目前兼容客户端较少

监控

MONITOR

自1.0.0可用。

时间复杂度:不明确。

语法:MONITOR
说明:

MONITOR 是一个调试命令,返回服务器处理的每一个命令,它能帮助我们了解在数据库上发生了什么操作,可以通过redis-cli和telnet命令使用.

$ redis-cli monitor
1339518083.107412 [0 127.0.0.1:60866] "keys" "*"
1339518087.877697 [0 127.0.0.1:60866] "dbsize"
1339518090.420270 [0 127.0.0.1:60866] "set" "x" "6"
1339518096.506257 [0 127.0.0.1:60866] "get" "x"
1339518099.363765 [0 127.0.0.1:60866] "del" "x"
1339518100.544926 [0 127.0.0.1:60866] "get" "x"

使用SIGINT (Ctrl-C)来停止 通过redis-cli使用 MONITOR 命令返回的输出.

$ telnet localhost 6379
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
MONITOR
+OK
+1339518083.107412 [0 127.0.0.1:60866] "keys" "*"
+1339518087.877697 [0 127.0.0.1:60866] "dbsize"
+1339518090.420270 [0 127.0.0.1:60866] "set" "x" "6"
+1339518096.506257 [0 127.0.0.1:60866] "get" "x"
+1339518099.363765 [0 127.0.0.1:60866] "del" "x"
+1339518100.544926 [0 127.0.0.1:60866] "get" "x"
QUIT
+OK
Connection closed by foreign host.

使用 QUIT 命令来停止通过telnet使用 MONITOR 返回的输出.

MONITOR 性能消耗

由于 MONITOR 命令返回 服务器处理的所有的 命令, 所以在性能上会有一些消耗.

在不运行 MONITOR 命令的情况下,benchmark的测试结果:

$ src/redis-benchmark -c 10 -n 100000 -q
PING_INLINE: 101936.80 requests per second
PING_BULK: 102880.66 requests per second
SET: 95419.85 requests per second
GET: 104275.29 requests per second
INCR: 93283.58 requests per second

在运行 MONITOR 命令的情况下,benchmark的测试结果: (redis-cli monitor > /dev/null):

$ src/redis-benchmark -c 10 -n 100000 -q
PING_INLINE: 58479.53 requests per second
PING_BULK: 59136.61 requests per second
SET: 41823.50 requests per second
GET: 45330.91 requests per second
INCR: 41771.09 requests per second

在这种特定的情况下,运行一个 MONITOR 命令能够降低50%的吞吐量,运行多个 MONITOR 命令 降低的吞吐量更多。

每个客户端都有自己的输出缓冲区,既然 MONITOR 能监听到所有的命令,一旦 Redis 的并发量过大 MONITOR 客户端的输出缓冲会暴涨,可能瞬间会占用大量内存。

返回值:

没有统一标准的返回值, 无限的返回服务器端处理的命令流.或 key 不存在,返回 0

示例:
# 方式一
C:
Users
zylia>redis-cli -a admin123 monitor OK 1498547986.670236 [0 127.0.0.1:63859] "AUTH" "admin123" 1498547986.670366 [0 127.0.0.1:63859] "GET" "hello" 1498548024.414979 [0 127.0.0.1:63869] "AUTH" "admin123" 1498548024.415185 [0 127.0.0.1:63869] "COMMAND" 1498548046.317448 [0 127.0.0.1:63872] "AUTH" "admin123" 1498548046.317742 [0 127.0.0.1:63872] "COMMAND" #方式二 登录后在进行 coderknock> MONITOR OK 1498548046.317448 [0 127.0.0.1:63872] "AUTH" "admin123" 1498548046.317742 [0 127.0.0.1:63872] "COMMAND" #方式三 Telnet C:
Users
zylia>telnet 127.0.0.1 6379 auth admin123 +OK MONITOR +OK +1498548296.621530 [0 127.0.0.1:64068] "AUTH" "admin123" +1498548296.621658 [0 127.0.0.1:64068] "GET" "hello" # 支持同时开启多个 MONITOR

其他配置

  • tcp-keepalive:检测TCP连接活性的周期,默认值为0,也就是不进行检测,如果需要设置,建议为60,那么Redis会每隔60秒对它创建的TCP连接进行活性检测,防止大量死连接占用系统资源。

  • tcp-backlog:TCP 三次握手后,会将接受的连接放入队列中,tcpbacklog就是队列的大小,它在 Redis 中的默认值是 511。通常来讲这个参数不需要调整,但是这个参数会受到操作系统的影响,例如在Linux操作系统中,如果/proc/sys/net/core/somaxconn小于tcp-backlog,那么在Redis启动时会看到如下日志,并建议将/proc/sys/net/core/somaxconn设置更大。

    WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/
    sys/net/core/somaxconn is set to the lower value of 128.
    

    修改方法也非常简单,只需要执行如下命令:

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

源码查看

我们来看下 Redis 源码中客户端部分的内容:

typedef struct client {
    uint64_t id;            /* Client incremental unique ID.客户端增量惟一的ID */
    int fd;                 /* Client socket. 客户端套接字*/
    redisDb *db;            /* Pointer to currently SELECTed DB. 指向当前选择的DB的指针*/
    robj *name;             /* As set by CLIENT SETNAME. 由客户端 SETNAME命令设置*/
    sds querybuf;           /* Buffer we use to accumulate client queries. 用来累积客户端查询的缓冲区*/
    sds pending_querybuf;   /* If this is a master, this buffer represents the
                               yet not applied replication stream that we
                               are receiving from the master.如果这是一个主服务器 ,这个缓冲区表示我们从主服务器接收到的未应用的复制流 */
    size_t querybuf_peak;   /* Recent (100ms or more) peak of querybuf size.最近(100ms 或者更长时间)querybuf 的峰值大小 */
    int argc;               /* Num of arguments of current command. 当前命令的参数个数*/
    robj **argv;            /* Arguments of current command. 当前命令的参数*/
    struct redisCommand *cmd, *lastcmd;  /* Last command executed. 最后一个被执行的命令*/
    int reqtype;            /* Request protocol type: PROTO_REQ_* 请求协议类型:PROTO_REQ_**/
    int multibulklen;       /* Number of multi bulk arguments left to read. 读取的多批量参数的数量*/
    long bulklen;           /* Length of bulk argument in multi bulk request. 多批量请求的批量参数的长度*/
    list *reply;            /* List of reply objects to send to the client.发送给客户端的应答对象列表(回复列表 有的翻译也叫动态缓冲区) */
    unsigned long long reply_bytes; /* Tot bytes of objects in reply list. 对象个数(列表长度)*/
    size_t sentlen;         /* Amount of bytes already sent in the current
                               buffer or object being sent. 在当前的缓冲区或对象已经发送的字节数*/
    time_t ctime;           /* Client creation time. 客户端创建时间*/
    time_t lastinteraction; /* Time of the last interaction, used for timeout 最后一次交互的时间,用于超时 */
    time_t obuf_soft_limit_reached_time;
    int flags;              /* Client flags: CLIENT_* macros. 客户端标志使用的是 CLIENT_* 宏指令(下面会列出)*/
    int authenticated;      /* When requirepass is non-NULL. 当 requirepass 不是 null 时会为变量赋值*/
    int replstate;          /* Replication state if this is a slave. 复制状态如果这是一个从机*/
    int repl_put_online_on_ack; /* Install slave write handler on ACK. */
    int repldbfd;           /* Replication DB file descriptor. */
    off_t repldboff;        /* Replication DB file offset. */
    off_t repldbsize;       /* Replication DB file size. */
    sds replpreamble;       /* Replication DB preamble. */
    long long read_reploff; /* Read replication offset if this is a master. */
    long long reploff;      /* Applied replication offset if this is a master. */
    long long repl_ack_off; /* Replication ack offset, if this is a slave. */
    long long repl_ack_time;/* Replication ack time, if this is a slave. */
    long long psync_initial_offset; /* FULLRESYNC reply offset other slaves
                                       copying this slave output buffer
                                       should use. */
    char replid[CONFIG_RUN_ID_SIZE+1]; /* Master replication ID (if master). */
    int slave_listening_port; /* As configured with: SLAVECONF listening-port */
    char slave_ip[NET_IP_STR_LEN]; /* Optionally given by REPLCONF ip-address */
    int slave_capa;         /* Slave capabilities: SLAVE_CAPA_* bitwise OR. */
    multiState mstate;      /* MULTI/EXEC state */
    int btype;              /* Type of blocking op if CLIENT_BLOCKED. */
    blockingState bpop;     /* blocking state */
    long long woff;         /* Last write global replication offset. */
    list *watched_keys;     /* Keys WATCHED for MULTI/EXEC CAS */
    dict *pubsub_channels;  /* channels a client is interested in (SUBSCRIBE) */
    list *pubsub_patterns;  /* patterns a client is interested in (SUBSCRIBE) */
    sds peerid;             /* Cached peer ID. */

    /* Response buffer 响应缓冲区(固定缓冲区)*/
    int bufpos;
    // 字节数组作为响应缓冲区 16K  */
    char buf[PROTO_REPLY_CHUNK_BYTES];//#define PROTO_REPLY_CHUNK_BYTES (16*1024) /* 16k output buffer
} client;

Client flags

/* Client flags */
#define CLIENT_SLAVE (1<<0)   /* This client is a slave server */
#define CLIENT_MASTER (1<<1)  /* This client is a master server */
#define CLIENT_MONITOR (1<<2) /* This client is a slave monitor, see MONITOR */
#define CLIENT_MULTI (1<<3)   /* This client is in a MULTI context */
#define CLIENT_BLOCKED (1<<4) /* The client is waiting in a blocking operation */
#define CLIENT_DIRTY_CAS (1<<5) /* Watched keys modified. EXEC will fail. */
#define CLIENT_CLOSE_AFTER_REPLY (1<<6) /* Close after writing entire reply. */
#define CLIENT_UNBLOCKED (1<<7) /* This client was unblocked and is stored in
                                  server.unblocked_clients */
#define CLIENT_LUA (1<<8) /* This is a non connected client used by Lua */
#define CLIENT_ASKING (1<<9)     /* Client issued the ASKING command */
#define CLIENT_CLOSE_ASAP (1<<10)/* Close this client ASAP */
#define CLIENT_UNIX_SOCKET (1<<11) /* Client connected via Unix domain socket */
#define CLIENT_DIRTY_EXEC (1<<12)  /* EXEC will fail for errors while queueing */
#define CLIENT_MASTER_FORCE_REPLY (1<<13)  /* Queue replies even if is master */
#define CLIENT_FORCE_AOF (1<<14)   /* Force AOF propagation of current cmd. */
#define CLIENT_FORCE_REPL (1<<15)  /* Force replication of current cmd. */
#define CLIENT_PRE_PSYNC (1<<16)   /* Instance don't understand PSYNC. */
#define CLIENT_READONLY (1<<17)    /* Cluster client is in read-only state. */
#define CLIENT_PUBSUB (1<<18)      /* Client is in Pub/Sub mode. */
#define CLIENT_PREVENT_AOF_PROP (1<<19)  /* Don't propagate to AOF. */
#define CLIENT_PREVENT_REPL_PROP (1<<20)  /* Don't propagate to slaves. */
#define CLIENT_PREVENT_PROP (CLIENT_PREVENT_AOF_PROP|CLIENT_PREVENT_REPL_PROP)
#define CLIENT_PENDING_WRITE (1<<21) /* Client has output to send but a write
                                        handler is yet not installed. */
#define CLIENT_REPLY_OFF (1<<22)   /* Don't send replies to client. */
#define CLIENT_REPLY_SKIP_NEXT (1<<23)  /* Set CLIENT_REPLY_SKIP for next cmd */
#define CLIENT_REPLY_SKIP (1<<24)  /* Don't send just this reply. */
#define CLIENT_LUA_DEBUG (1<<25)  /* Run EVAL in debug mode. */
#define CLIENT_LUA_DEBUG_SYNC (1<<26)  /* EVAL debugging without fork() */
#define CLIENT_MODULE (1<<27) /* Non connected client used by some module. */

INFO

判断元素是否存在集合中

INFO

自1.0.0可用。

时间复杂度:O(1)。

语法:INFO [section]
说明:

INFO命令以一种易于理解和阅读的格式,返回关于Redis服务器的各种信息和统计数值。

通过给定可选的参数 section ,可以让命令只返回某一部分的信息:

  • server: Redis服务器的一般信息
  • clients: 客户端的连接部分
  • memory: 内存消耗相关信息
  • persistence: RDB和AOF相关信息
  • stats: 一般统计
  • replication: 主/从复制信息
  • cpu: 统计CPU的消耗
  • commandstats: Redis命令统计
  • cluster: Redis集群信息
  • keyspace: 数据库的相关统计

它也可以采取以下值:

  • all: 返回所有信息
  • default: 值返回默认设置的信息

如果没有使用任何参数时,默认为default

请注意不同Redis版本会添加或者删除一些字段。一个健壮的客户端应用解析该命令的结果时,应该跳过未知的字段,并且优雅的处理缺少的字段。

已下描述要求 Redis >= 2.4

下面是所有 server (记录了 Redis 服务器的信息)相关的信息:

  • redis_version: Redis 服务器版本
  • redis_git_sha1: Git SHA1
  • redis_git_dirty: Git dirty flag
  • os: Redis 服务器的宿主操作系统
  • arch_bits: 架构(32 或 64 位)
  • multiplexing_api: Redis 所使用的事件处理机制
  • gcc_version: 编译 Redis 时所使用的 GCC 版本
  • process_id: 服务器进程的 PID
  • run_id: Redis 服务器的随机标识符(用于 Sentinel 和集群)
  • tcp_port: TCP/IP 监听端口
  • uptime_in_seconds: 自 Redis 服务器启动以来,经过的秒数
  • uptime_in_days: 自 Redis 服务器启动以来,经过的天数
  • lru_clock: 以分钟为单位进行自增的时钟,用于 LRU 管理

下面是所有 clients(记录了已连接客户端的信息) 相关的信息:

  • connected_clients: 已连接客户端的数量(不包括通过从属服务器连接的客户端)
  • client_longest_output_list: 当前连接的客户端当中,最长的输出列表
  • client_biggest_input_buf: 当前连接的客户端当中,最大输入缓存
  • blocked_clients: 正在等待阻塞命令(BLPOP、BRPOP、BRPOPLPUSH)的客户端的数量

下面是所有 memory (记录了服务器的内存信息)相关的信息:

  • used_memory: 由 Redis 分配器分配的内存总量,以字节(byte)为单位
  • used_memory_human: 以人类可读的格式返回 Redis 分配的内存总量
  • used_memory_rss: 从操作系统的角度,返回 Redis 已分配的内存总量(俗称常驻集大小)。这个值和 top 、 ps 等命令的输出一致。
  • used_memory_peak: Redis 的内存消耗峰值(以字节为单位)
  • used_memory_peak_human: 以人类可读的格式返回 Redis 的内存消耗峰值
  • used_memory_lua: Lua 引擎所使用的内存大小(以字节为单位)
  • mem_fragmentation_ratio: used_memory_rssused_memory 之间的比率
  • mem_allocator: 在编译时指定的, Redis 所使用的内存分配器。可以是 libc 、 jemalloc 或者 tcmalloc 。 在理想情况下, used_memory_rss 的值应该只比 used_memory 稍微高一点儿。

当 rss > used ,且两者的值相差较大时,表示存在(内部或外部的)内存碎片。

内存碎片的比率可以通过 mem_fragmentation_ratio 的值看出。

当 used > rss 时,表示 Redis 的部分内存被操作系统换出到交换空间了,在这种情况下,操作可能会产生明显的延迟。

由于Redis无法控制其分配如何被映射到内存页面,因此较高的 usedmemoryrss 通常是内存使用量激增的结果。

当 Redis 释放内存时,分配器可能会,也可能不会,将内存返还给操作系统。

如果 Redis 释放了内存,却没有将内存返还给操作系统,那么 used_memory 的值可能和操作系统显示的 Redis 内存占用并不一致。

查看 used_memory_peak 的值可以验证这种情况是否发生。

下面是所有 persistence (记录了跟 RDB 持久化和 AOF 持久化有关的信息)相关的信息:

  • loading : 一个标志值,记录了服务器是否正在载入持久化文件。
  • rdb_changes_since_last_save : 距离最近一次成功创建持久化文件之后,经过了多少秒。
  • rdb_bgsave_in_progress : 一个标志值,记录了服务器是否正在创建 RDB 文件。
  • rdb_last_save_time : 最近一次成功创建 RDB 文件的 UNIX 时间戳。
  • rdb_last_bgsave_status : 一个标志值,记录了最近一次创建 RDB 文件的结果是成功还是失败。
  • rdb_last_bgsave_time_sec : 记录了最近一次创建 RDB 文件耗费的秒数。
  • rdb_current_bgsave_time_sec : 如果服务器正在创建 RDB 文件,那么这个域记录的就是当前的创建操作已经耗费的秒数。
  • aof_enabled : 一个标志值,记录了 AOF 是否处于打开状态。
  • aof_rewrite_in_progress : 一个标志值,记录了服务器是否正在创建 AOF 文件。
  • aof_rewrite_scheduled : 一个标志值,记录了在 RDB 文件创建完毕之后,是否需要执行预约的 AOF 重写操作。
  • aof_last_rewrite_time_sec : 最近一次创建 AOF 文件耗费的时长。
  • aof_current_rewrite_time_sec : 如果服务器正在创建 AOF 文件,那么这个域记录的就是当前的创建操作已经耗费的秒数。
  • aof_last_bgrewrite_status : 一个标志值,记录了最近一次创建 AOF 文件的结果是成功还是失败。

如果 AOF 持久化功能处于开启状态,那么这个部分还会加上以下字段:

  • aof_current_size : AOF 文件目前的大小。
  • aof_base_size : 服务器启动时或者 AOF 重写最近一次执行之后,AOF 文件的大小。
  • aof_pending_rewrite : 一个标志值,记录了是否有 AOF 重写操作在等待 RDB 文件创建完毕之后执行。
  • aof_buffer_length : AOF 缓冲区的大小。
  • aof_rewrite_buffer_length : AOF 重写缓冲区的大小。
  • aof_pending_bio_fsync : 后台 I/O 队列里面,等待执行的 fsync 调用数量。
  • aof_delayed_fsync : 被延迟的 fsync 调用数量。

If a load operation is on-going, these additional fields will be added:

  • loading_start_time: Epoch-based timestamp of the start of the load operation
  • loading_total_bytes: Total file size
  • loading_loaded_bytes: Number of bytes already loaded
  • loading_loaded_perc: Same value expressed as a percentage
  • loading_eta_seconds: ETA in seconds for the load to be complete

下面是所有 stats(记录了一般统计信息)相关的信息:

  • total_connections_received : 服务器已接受的连接请求数量。
  • total_commands_processed : 服务器已执行的命令数量。
  • instantaneous_ops_per_sec : 服务器每秒钟执行的命令数量。
  • rejected_connections : 因为最大客户端数量限制而被拒绝的连接请求数量。
  • expired_keys : 因为过期而被自动删除的数据库键数量。
  • evicted_keys : 因为最大内存容量限制而被驱逐(evict)的键数量。
  • keyspace_hits : 查找数据库键成功的次数。
  • keyspace_misses : 查找数据库键失败的次数。
  • pubsub_channels : 目前被订阅的频道数量。
  • pubsub_patterns : 目前被订阅的模式数量。
  • latest_fork_usec : 最近一次 fork() 操作耗费的毫秒数。

下面是所有 replication(主/从复制信息) 相关的信息:

  • role : 如果当前服务器没有在复制任何其他服务器,那么这个域的值就是 master ;否则的话,这个域的值就是 slave。注意,在创建复制链的时候,一个从服务器也可能是另一个服务器的主服务器。

    如果当前服务器是一个从服务器的话,那么这个部分还会加上以下字段:

  • master_host : 主服务器的 IP 地址。

  • master_port : 主服务器的 TCP 监听端口号。

  • master_link_status : 复制连接当前的状态, up 表示连接正常, down 表示连接断开。

  • master_last_io_seconds_ago : 距离最近一次与主服务器进行通信已经过去了多少秒钟。

  • master_sync_in_progress : 一个标志值,记录了主服务器是否正在与这个从服务器进行同步。

    如果同步操作正在进行,那么这个部分还会加上以下字段:

  • master_sync_left_bytes : 距离同步完成还缺少多少字节数据。

  • master_sync_last_io_seconds_ago : 距离最近一次因为 SYNC 操作而进行 I/O 已经过去了多少秒。

    如果主从服务器之间的连接处于断线状态,那么这个部分还会加上以下字段:

  • master_link_down_since_seconds : 主从服务器连接断开了多少秒。

    以下是一些总会出现的字段:

  • connected_slaves : 已连接的从服务器数量。

    对于每个从服务器,都会添加以下一行信息:

  • slaveXXX : ID、IP 地址、端口号、连接状态

下面是所有 cpu 相关的信息:

  • used_cpu_sys : Redis 服务器耗费的系统 CPU 。
  • used_cpu_user : Redis 服务器耗费的用户 CPU 。
  • used_cpu_sys_children : 后台进程耗费的系统 CPU 。
  • used_cpu_user_children : 后台进程耗费的用户 CPU 。
  • commandstats 部分记录了各种不同类型的命令的执行统计信息,比如命令执行的次数、命令耗费的 CPU 时间、执行每个命令耗费的平均 CPU 时间等等。对于每种类型的命令,这个部分都会添加一行以下格式的信息:
  • cmdstat_XXX:calls=XXX,usec=XXX,usecpercall=XXX
  • cluster 部分记录了和集群有关的信息,它包含以下域:
  • cluster_enabled : 一个标志值,记录集群功能是否已经开启。
  • keyspace 部分记录了数据库相关的统计信息,比如数据库的键数量、数据库已经被删除的过期键数量等。对于每个数据库,这个部分都会添加一行以下格式的信息:
  • dbXXX:keys=XXX,expires=XXX

除上面给出的这些值以外, section 参数的值还可以是下面这两个:

  • all : 返回所有信息
  • default : 返回默认选择的信息
返回值:

具体请参见下面的测试代码。

示例:
coderknock> INFO
# Server
redis_version:3.2.100
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:dd26f1f93c5130ee
redis_mode:standalone
os:Windows
arch_bits:64
multiplexing_api:WinSock_IOCP
process_id:19944
run_id:472a23ff45a04eb3081b48078a0c619c26376ddf
tcp_port:6379
uptime_in_seconds:268
uptime_in_days:0
hz:10
lru_clock:5378046
executable:D:
redis
redis-server.exe config_file:D:
redis
redis.windows.conf # Clients connected_clients:1 client_longest_output_list:0 client_biggest_input_buf:0 blocked_clients:0 # Memory used_memory:711792 used_memory_human:695.11K used_memory_rss:674008 used_memory_rss_human:658.21K used_memory_peak:787952 used_memory_peak_human:769.48K total_system_memory:0 total_system_memory_human:0B used_memory_lua:37888 used_memory_lua_human:37.00K maxmemory:0 maxmemory_human:0B maxmemory_policy:noeviction mem_fragmentation_ratio:0.95 mem_allocator:jemalloc-3.6.0 # Persistence loading:0 rdb_changes_since_last_save:0 rdb_bgsave_in_progress:0 rdb_last_save_time:1498550002 rdb_last_bgsave_status:ok rdb_last_bgsave_time_sec:-1 rdb_current_bgsave_time_sec:-1 aof_enabled:0 aof_rewrite_in_progress:0 aof_rewrite_scheduled:0 aof_last_rewrite_time_sec:-1 aof_current_rewrite_time_sec:-1 aof_last_bgrewrite_status:ok aof_last_write_status:ok # Stats total_connections_received:2 total_commands_processed:6 instantaneous_ops_per_sec:0 total_net_input_bytes:165 total_net_output_bytes:11895644 instantaneous_input_kbps:0.02 instantaneous_output_kbps:2286.67 rejected_connections:0 sync_full:0 sync_partial_ok:0 sync_partial_err:0 expired_keys:0 evicted_keys:0 keyspace_hits:1 keyspace_misses:0 pubsub_channels:0 pubsub_patterns:0 latest_fork_usec:0 migrate_cached_sockets:0 # Replication role:master connected_slaves:0 master_repl_offset:0 repl_backlog_active:0 repl_backlog_size:1048576 repl_backlog_first_byte_offset:0 repl_backlog_histlen:0 # CPU used_cpu_sys:0.20 used_cpu_user:0.11 used_cpu_sys_children:0.00 used_cpu_user_children:0.00 # Cluster cluster_enabled:0 # Keyspace db0:keys=43,expires=0,avg_ttl=0 db1:keys=3,expires=0,avg_ttl=0