Redis `CLIENT LIST` 与 `CLIENT KILL`:连接管理与异常客户端处理

好的,各位观众老爷,今天咱们来聊聊 Redis 里那些“管人”的工具——CLIENT LISTCLIENT KILL。哎,别想歪了,这里的“人”指的是连接到 Redis 服务器的客户端。

想象一下,Redis 服务器就像一家热闹的咖啡馆,客人(客户端)络绎不绝,有的安静地品尝咖啡(执行读取操作),有的高谈阔论(执行写入操作),有的甚至霸占着位置啥也不干(空闲连接)。作为咖啡馆的店长(Redis 服务器管理员),你不仅要保证咖啡的质量,还要维护咖啡馆的秩序,及时清理掉那些“捣乱分子”。

CLIENT LISTCLIENT KILL 就是你维护秩序的两大法宝。一个负责点名,看看都有哪些客人在店里;一个负责请人走,把那些不守规矩的客人“请”出去。

一、点名大法:CLIENT LIST

CLIENT LIST 命令就像咖啡馆的点名册,它会列出所有连接到 Redis 服务器的客户端信息。这些信息非常详细,包括客户端的 ID、地址、状态、命令等等,简直就是一份详细的“客户档案”。

1. 语法和输出

语法非常简单:

CLIENT LIST

输出的信息可就丰富了,每一行代表一个客户端的信息,各个字段之间用空格分隔。例如:

id=1 addr=127.0.0.1:6379 laddr=127.0.0.1:50000 fd=6 name= myclient age=12 idle=5 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 tot-mem=20480 events=r cmd=ping user=default client-type=normal
id=2 addr=127.0.0.1:6380 laddr=127.0.0.1:50001 fd=7 name= another_client age=8 idle=2 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 tot-mem=20480 events=r cmd=get user=default client-type=normal

看起来是不是有点眼花缭乱?没关系,我们来逐一解读这些字段:

字段 含义
id 客户端的唯一 ID,每次连接都会分配一个新的 ID。
addr 客户端的 IP 地址和端口号。
laddr Redis服务器监听的地址
fd 客户端连接的文件描述符,相当于咖啡馆里座位的编号。
name 客户端的名称,可以通过 CLIENT SETNAME 命令设置,方便识别。就像给常客起了个昵称,方便你记住他。
age 客户端的连接时长,单位是秒。
idle 客户端的空闲时长,单位是秒。如果一个客户端长时间没有发送任何命令,那么它的 idle 值会不断增加。这就像客人霸占着位置啥也不干,影响咖啡馆的翻台率。
flags 客户端的标志位,表示客户端的状态。例如,N 表示正常连接,b 表示正在阻塞,x 表示正在执行事务。
db 客户端当前选择的数据库编号。
sub 客户端订阅的频道数量。
psub 客户端订阅的模式数量。
multi 客户端是否正在执行事务。-1 表示没有执行事务,其他值表示事务中执行的命令数量。
qbuf 客户端的查询缓冲区大小,单位是字节。
qbuf-free 客户端的查询缓冲区剩余空间大小,单位是字节。
obl 客户端的输出缓冲区大小,单位是字节。
oll 客户端的输出列表长度。
omem 客户端的输出缓冲区使用的内存大小,单位是字节。
tot-mem 客户端连接的总内存使用量,单位是字节。
events 客户端的事件类型,r 表示可读,w 表示可写。
cmd 客户端最后执行的命令。
user 客户端的用户名,如果 Redis 启用了 ACL(访问控制列表),那么会显示客户端的用户名。
client-type 客户端的类型, normal, master, replica, pubsub

2. CLIENT LIST 的应用场景

  • 监控连接数: 了解当前有多少客户端连接到 Redis 服务器,可以帮助你判断服务器的负载情况。
  • 识别慢客户端: 通过 idle 字段可以找到长时间空闲的客户端,及时清理掉这些“僵尸连接”,释放资源。
  • 排查问题: 通过 cmd 字段可以了解客户端最后执行的命令,有助于排查客户端的错误。
  • 安全审计: 通过 addruser 字段可以了解客户端的来源和身份,有助于进行安全审计。

3. CLIENT LIST 的一些小技巧

  • 格式化输出: 如果觉得 CLIENT LIST 的输出太乱,可以使用 awkgrep 等工具进行格式化,提取你关心的字段。
  • 结合脚本: 可以编写脚本,定期执行 CLIENT LIST 命令,分析客户端的连接情况,并根据预设的规则自动清理空闲连接。

二、请君入瓮:CLIENT KILL

CLIENT KILL 命令就像咖啡馆的保安,专门负责把那些不守规矩的客人“请”出去。它可以根据不同的条件,关闭指定的客户端连接。

1. 语法和选项

CLIENT KILL 命令的语法比较灵活,可以通过多种方式指定要关闭的客户端:

CLIENT KILL [ip:port] [ID client-id] [TYPE normal|master|replica|pubsub] [USER username] [ADDR ip:port] [SKIPME yes|no]
  • ip:port 根据客户端的 IP 地址和端口号关闭连接。例如,CLIENT KILL 127.0.0.1:6380 会关闭 IP 地址为 127.0.0.1,端口号为 6380 的客户端连接。
  • ID client-id 根据客户端的 ID 关闭连接。例如,CLIENT KILL ID 2 会关闭 ID 为 2 的客户端连接。
  • TYPE normal|master|replica|pubsub 根据客户端的类型关闭连接。例如,CLIENT KILL TYPE normal 会关闭所有普通客户端连接。
  • USER username 根据客户端的用户名关闭连接。例如,CLIENT KILL USER myuser 会关闭所有用户名为 myuser 的客户端连接。
  • ADDR ip:port 根据客户端的 IP 地址和端口号关闭连接。和直接使用 ip:port 参数效果一样。
  • SKIPME yes|no 指定是否跳过当前客户端。默认值为 yes,表示跳过当前客户端。设置为 no 时,会关闭当前客户端的连接,相当于自杀。

2. CLIENT KILL 的使用场景

  • 清理空闲连接: 可以使用 CLIENT KILL 命令关闭长时间空闲的客户端连接,释放资源。
  • 强制断开恶意连接: 如果发现有恶意客户端连接到 Redis 服务器,可以使用 CLIENT KILL 命令立即断开连接,防止恶意行为。
  • 重启 Redis 集群: 在重启 Redis 集群之前,可以使用 CLIENT KILL TYPE normal 命令关闭所有普通客户端连接,确保数据的一致性。
  • 限制用户访问: 如果 Redis 启用了 ACL,可以使用 CLIENT KILL USER username 命令限制指定用户的访问。

3. CLIENT KILL 的注意事项

  • 谨慎使用: CLIENT KILL 命令会强制断开客户端连接,可能会导致客户端的数据丢失或操作失败。因此,在使用 CLIENT KILL 命令之前,一定要仔细确认要关闭的客户端是否正确。
  • 避免频繁执行: 频繁执行 CLIENT KILL 命令会增加 Redis 服务器的负担,影响性能。建议只在必要的时候使用 CLIENT KILL 命令。
  • 权限控制: CLIENT KILL 命令属于管理命令,需要具有相应的权限才能执行。如果 Redis 启用了 ACL,需要确保当前用户具有 KILL 权限。

4. 案例分析:清理空闲连接

假设我们需要清理所有空闲时间超过 60 秒的客户端连接,可以编写一个脚本来实现:

#!/bin/bash

# 获取所有客户端信息
CLIENT_LIST=$(redis-cli CLIENT LIST)

# 循环遍历客户端信息
while read -r CLIENT_INFO; do
  # 提取 idle 时间
  IDLE_TIME=$(echo "$CLIENT_INFO" | awk '{for (i=1; i<=NF; i++) {if ($i ~ /^idle=/) {print substr($i, 6)}}}')

  # 判断 idle 时间是否超过 60 秒
  if [ "$IDLE_TIME" -gt 60 ]; then
    # 提取客户端 ID
    CLIENT_ID=$(echo "$CLIENT_INFO" | awk '{for (i=1; i<=NF; i++) {if ($i ~ /^id=/) {print substr($i, 4)}}}')

    # 关闭客户端连接
    redis-cli CLIENT KILL ID "$CLIENT_ID"
    echo "Killed client with ID: $CLIENT_ID"
  fi
done <<< "$CLIENT_LIST"

这个脚本首先使用 redis-cli CLIENT LIST 命令获取所有客户端信息,然后循环遍历每一条客户端信息,提取 idle 时间,如果 idle 时间超过 60 秒,则提取客户端 ID,并使用 redis-cli CLIENT KILL ID "$CLIENT_ID" 命令关闭客户端连接。

三、进阶技巧:结合 Lua 脚本

为了提高效率,可以将 CLIENT LISTCLIENT KILL 命令结合到 Lua 脚本中执行。Lua 脚本可以一次性执行多个 Redis 命令,减少网络开销。

例如,可以使用以下 Lua 脚本清理所有空闲时间超过 60 秒的客户端连接:

local clients = redis.call('CLIENT', 'LIST')
local lines = string.gmatch(clients, '[^rn]+')
for line in lines do
  local idle = string.match(line, 'idle=([%d]+)')
  if idle and tonumber(idle) > 60 then
    local id = string.match(line, 'id=([%d]+)')
    if id then
      redis.call('CLIENT', 'KILL', 'ID', id)
      redis.log(redis.LOG_NOTICE, 'Killed client with ID: ' .. id)
    end
  end
end
return 'OK'

可以使用 redis-cli EVAL 命令执行这个 Lua 脚本:

redis-cli EVAL "$(cat cleanup_idle_clients.lua)" 0

四、总结

CLIENT LISTCLIENT KILL 是 Redis 连接管理的重要工具。CLIENT LIST 让你对客户端的连接情况了如指掌,CLIENT KILL 让你能够及时清理掉那些“捣乱分子”,维护 Redis 服务器的秩序。

掌握这两个命令,就像掌握了咖啡馆的经营之道,让你能够轻松管理你的 Redis 服务器,保证其稳定高效运行。

希望今天的分享对大家有所帮助!如果有什么问题,欢迎在评论区留言。下次再见!👋

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注