文章

Redis - misc

记录 Redis runtime config、slowlog 和 monitor 三个小功能,重点看它们如何复用 redisServer 中的配置、链表和 client 监听机制。

Redis 其他值得一提的小功能。它们看起来零散,但背后的思路很统一:运行时配置改状态,慢日志用内存链表记事件,monitor 用 client 列表广播命令

  1. runtime config
  2. slowlog
  3. monitor
  4. 小结

runtime config

可以用 CONFIG SET <key> <value> 进行 runtime 配置:

1
CONFIG SET slowlog-log-slower-than 10000

也可以用 CONFIG GET <key> 查看:

1
CONFIG GET slowlog-*

它的本质不是魔法,就是把配置项映射到 redisServer 里的字段。能运行时改的配置,Redis 收到命令后就校验参数、更新内存里的配置值;不能运行时改的配置,就不会让你通过 CONFIG SET 瞎折腾。

如果希望把运行时修改写回配置文件,还要看具体版本和配置项是否支持 CONFIG REWRITE。否则进程重启之后,内存里的修改就没了。

flowchart LR
    Client["client"] --> Cmd["CONFIG SET/GET"]
    Cmd --> Check{"配置项是否允许运行时修改"}
    Check -- "否" --> Error["返回错误"]
    Check -- "是" --> Server["更新 redisServer 配置字段"]
    Server --> Effect["后续逻辑按新值运行"]
    Server -. "可选" .-> Rewrite["CONFIG REWRITE 写回配置文件"]

    style Server fill:#e8f5e9,stroke:#81c784
    style Error fill:#ffe3e3,stroke:#ff8787

slowlog

Redis 和 MySQL 一样,也有慢查询日志。

redis.conf 里可以配置:

1
2
slowlog-log-slower-than <microseconds>
slowlog-max-len <number>

注意第一个配置的单位是微秒,不是毫秒。这个地方很容易顺手写错,毕竟平时说慢查询都喜欢说“多少毫秒”。Redis 偏不,它用微秒,嗯,很 Redis。

  • slowlog-log-slower-than:执行时间超过多少微秒的命令会被记录;
  • slowlog-max-len:最多保存多少条慢日志。

实际实现上,Redis 在 redisServer 里用链表保存符合条件的 command,默认不持久化。也就是说,slowlog 是诊断用的内存结构,不是审计日志。

常用命令:

1
2
3
SLOWLOG LEN
SLOWLOG GET
SLOWLOG RESET

这里原来容易写成 SLOTLOG RESET,但正确命令是 SLOWLOG RESET。Redis 没有一个慢 slot 日志在那儿等着我们召唤。

flowchart TD
    Command["执行命令"] --> Measure["统计执行耗时"]
    Measure --> Slow{"耗时 > slowlog-log-slower-than?"}
    Slow -- "否" --> Done["正常结束"]
    Slow -- "是" --> Append["追加 slowlog 链表"]
    Append --> Trim{"长度超过 slowlog-max-len?"}
    Trim -- "是" --> DropOld["删除最旧记录"]
    Trim -- "否" --> Done

    style Append fill:#fff3bf,stroke:#f0c36d
    style DropOld fill:#ffe3e3,stroke:#ff8787

工程含义也很简单:

  • slowlog 记录的是命令执行时间,不包含排队等待、网络传输这些时间;
  • 它保存在内存里,重启就没了;
  • 它适合定位“哪个命令本身慢”,不适合当完整请求链路追踪。

monitor

MONITOR 可以把一个 client 变成当前 server 的 monitor,实时打印 server 收到的命令。

实现也很简单,和 pub-sub、listener 的味道一样:

  1. client 执行 MONITOR
  2. Redis 把这个 client 放进 monitors 列表;
  3. server 每收到一条命令,就遍历 monitors,把命令文本发给它们。
sequenceDiagram
    participant App as 普通 client
    participant Redis as Redis server
    participant Mon as monitor client

    Mon->>Redis: MONITOR
    Redis->>Redis: 记录 monitor client
    App->>Redis: SET a 1
    Redis-->>Mon: 推送 SET a 1
    App->>Redis: GET a
    Redis-->>Mon: 推送 GET a

MONITOR 很适合临时观察“到底谁在打这个 Redis”,但它不是免费午餐:

  • 命令很多时,monitor client 会收到大量输出;
  • Redis 需要额外把命令推给 monitor client;
  • 线上使用要谨慎,尤其是高流量实例。

小结

这几个功能都不大,但能看到 Redis 一贯的实现风格:

  • 能用已有 server 字段表达的,就直接更新字段;
  • 能用链表保存的,就先放内存链表;
  • 能通过 client 列表广播的,就遍历 client 发送。

功能小,不代表没用。很多线上排障时候,CONFIG GETSLOWLOG GETMONITOR 比复杂工具还快。只不过 MONITOR 这种工具要轻拿轻放,不然排障的人也可能变成新的故障源。

本文由作者按照 CC BY 4.0 进行授权