跳到主要内容

监控、安全与性能优化

没有监控就无法判断调优是否有效;没有安全边界,性能再好也不能上线。本章先建立指标和告警,再处理 ACL/TLS,最后讨论 BigKey、HotKey 和内核参数。

1. Redis 监控分四层

层次关注点数据来源
可用性能否连接、角色、Cluster/Sentinel 状态exporter、PING、合成探测
容量内存、key 数、磁盘、连接、复制 backlogINFO、node exporter
性能ops/sec、延迟、慢日志、CPU、网络INFO、LATENCY、系统指标
正确性复制、持久化、淘汰、写入错误INFO、日志、应用指标

只监控 PING 会漏掉“进程活着但不能持久化”“主从断链”“内存满后写失败”等问题。

2. 部署 redis_exporter

先创建只读监控 ACL 用户,按 exporter 实际所需命令授权,不要复用应用或管理员密码。下面以容器为例:

user monitor on >替换为随机密码 ~* +ping +info +client|getname +config|get +scan +slowlog +latency

如果 exporter 日志出现 NOPERM,根据它实际调用的命令补充单项权限,不要直接给 +@all

services:
redis-exporter:
image: oliver006/redis_exporter:v1.67.0
environment:
REDIS_ADDR: redis://redis:6379
REDIS_USER: monitor
REDIS_PASSWORD: ${REDIS_MONITOR_PASSWORD}
ports:
- "127.0.0.1:9121:9121"

Prometheus 配置:

scrape_configs:
- job_name: redis
scrape_interval: 15s
static_configs:
- targets:
- redis-exporter-1:9121
- redis-exporter-2:9121

启动后验证:

curl -fsS http://127.0.0.1:9121/metrics | head

3. 新手先看这些指标

内存

  • used_memory / maxmemory:数据离上限还有多远;
  • used_memory_rss:操作系统实际分配;
  • mem_fragmentation_ratio:需结合 used/RSS 判断,不能只看一个比值;
  • evicted_keys:发生淘汰,说明容量或策略已介入业务。

客户端和命令

  • connected_clients 接近 maxclients
  • blocked_clients 持续大于 0;
  • instantaneous_ops_per_sec 与历史基线偏离;
  • keyspace hits/misses 用于计算缓存命中率;
  • rejected connections 表示连接已被拒绝。

持久化与复制

  • RDB/AOF 最近执行状态不是 ok
  • AOF rewrite 长时间未完成;
  • master_link_status 为 down;
  • 主从 offset 差距持续扩大;
  • Cluster 状态非 ok 或 slot 缺失。

4. 告警应包含持续时间和处置入口

groups:
- name: redis
rules:
- alert: RedisMemoryNearLimit
expr: redis_memory_used_bytes / redis_memory_max_bytes > 0.85
for: 10m
labels:
severity: warning
annotations:
summary: Redis 内存持续超过上限的 85%

- alert: RedisReplicationBroken
expr: redis_connected_slaves < 1
for: 2m
labels:
severity: critical

生产规则需按 exporter 实际指标名和架构调整。告警描述应包含实例、角色、看板和运行手册链接,避免只发一句“Redis Down”。

5. 网络、ACL 与 TLS

Redis 不直接暴露公网。使用私网监听、安全组/防火墙、ACL 最小权限和 TLS。危险命令权限只给受审计的运维用户。

port 0
tls-port 6379
tls-cert-file /etc/redis/tls/redis.crt
tls-key-file /etc/redis/tls/redis.key
tls-ca-cert-file /etc/redis/tls/ca.crt
tls-auth-clients yes
redis-cli --tls \
--cacert /etc/redis/tls/ca.crt \
--cert /etc/redis/tls/client.crt \
--key /etc/redis/tls/client.key \
-h redis.internal.example.com -p 6379 --user app PING

验证证书域名、有效期和 CA 链。Sentinel、复制、Cluster bus 和 exporter 也要按实际版本与部署方式配置相应 TLS/认证,不能只加密应用入口。

6. BigKey:一个 key 拖慢整个实例

BigKey 可能是 20 MB 字符串,也可能是有百万成员的集合。影响包括网络传输长、删除慢、复制和持久化放大、迁 slot 困难。

# 在低峰或副本扫描候选
redis-cli --bigkeys

# 对候选精确确认
redis-cli TYPE candidate:key
redis-cli MEMORY USAGE candidate:key SAMPLES 10
redis-cli HLEN candidate:key
redis-cli LLEN candidate:key
redis-cli SCARD candidate:key
redis-cli ZCARD candidate:key

治理方式是拆 key、限制集合长度、压缩 value、分页读取;删除使用 UNLINK 并监控后台释放造成的 CPU 压力。

7. HotKey:少数 key 吃掉大部分 QPS

HotKey 常表现为单线程 CPU 高、某个 Cluster 主节点明显更忙、网络出入流量集中。优先从应用埋点、代理日志或客户端采样定位;redis-cli --hotkeys 依赖 LFU 且会扫描 keyspace,只在受控环境使用。

治理包括本地缓存、请求合并、拆分 key、只读副本、限流和避免同一 hash tag 集中全部流量。单纯扩容 Cluster 但热点仍在一个 slot,问题不会消失。

8. Pipeline 和连接池

Pipeline 将多条命令一次发送,减少网络往返。可以在隔离实例用 redis-benchmark 比较不同 pipeline 深度:

redis-benchmark -t set,get -n 10000 -c 20 -P 1 -q
redis-benchmark -t set,get -n 10000 -c 20 -P 16 -q

批次过大会占用输入/输出缓冲并让其他请求等待。应用应限制单批命令和响应字节数。连接池也不是越大越好:总连接数约等于应用实例数 × 每实例池大小,必须与 maxclients、fd 和故障重连风暴一起规划。

9. Linux 基础参数

# /etc/sysctl.d/99-redis.conf
vm.overcommit_memory = 1
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
sudo sysctl --system
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

THP 往往造成延迟抖动;Swap 会产生不可预测延迟,应靠容量规划避免常态使用。NUMA、CPU 绑核、网卡和 TCP 参数必须压测,不要照搬所谓“万能调优配置”。

10. 调优闭环

  1. 明确现象和目标指标;
  2. 保存变更前基线;
  3. 一次只调整一个变量;
  4. 在预发或影子流量压测;
  5. 比较吞吐、P50/P95/P99、错误率和资源;
  6. 准备回滚并观察足够时间;
  7. 将最终参数写回配置管理与运行手册。