1. 问题描述重构

当前遇到一个生产环境紧急故障:一个支撑上万家企业的SaaS平台Redis集群,承担着商品、支付、物流、营销等多个核心服务的数据存储。集群入流量突然被打满(达到4-6GB/s),导致部分服务不可用并报错。急需快速定位:

  1. 哪个或哪些Key被异常频繁调用(热Key问题)

  2. 哪个客户端IP在发送大量请求(异常源头)

  3. 每个客户端的确切入流量数据(精准定位)


2. 排查原理与实战示例

排查原理图

image

 

3. 实战命令与示例输出

3.1. 查看实时状态(首要诊断)

命令:

redis-cli -h 192.168.1.100 -p 6379 -a yourpassword --stat

示例输出(异常情况):

------- data ------ --------------------- load -------------------- - child -
keys       mem      clients blocked requests            connections
5000000    15.8G    250     0       1850000000(+850000) 250

分析:每秒请求数增加85万(+850000),明显异常。

3.2. 分析客户端连接(定位异常源头)

命令:

redis-cli -h 192.168.1.100 -p 6379 -a yourpassword client list

示例输出(异常模式1:代码BUG):

[root@zb-yunweitest-mysql-204-201 data]# redis-cli -h 172.21.204.201  client list
id=53 addr=172.21.204.200:46102 laddr=172.21.204.201:6379 fd=8 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=40954 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12644392 events=rw cmd=get user=default redir=-1
id=54 addr=172.21.204.200:46104 laddr=172.21.204.201:6379 fd=9 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12603440 events=rw cmd=get user=default redir=-1
id=55 addr=172.21.204.200:46106 laddr=172.21.204.201:6379 fd=10 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12603440 events=rw cmd=get user=default redir=-1
id=56 addr=172.21.204.200:46108 laddr=172.21.204.201:6379 fd=11 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12603440 events=rw cmd=get user=default redir=-1
id=57 addr=172.21.204.200:46110 laddr=172.21.204.201:6379 fd=12 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12603440 events=rw cmd=get user=default redir=-1
id=58 addr=172.21.204.200:46112 laddr=172.21.204.201:6379 fd=13 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12603440 events=rw cmd=get user=default redir=-1
id=59 addr=172.21.204.200:46114 laddr=172.21.204.201:6379 fd=14 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12603440 events=rw cmd=get user=default redir=-1
id=60 addr=172.21.204.200:46116 laddr=172.21.204.201:6379 fd=15 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12603440 events=rw cmd=get user=default redir=-1
id=61 addr=172.21.204.200:46118 laddr=172.21.204.201:6379 fd=16 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12603440 events=rw cmd=get user=default redir=-1
id=62 addr=172.21.204.200:46120 laddr=172.21.204.201:6379 fd=17 name= age=9 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 argv-mem=0 obl=0 oll=1 omem=12582936 tot-mem=12603440 events=rw cmd=get user=default redir=-1
id=64 addr=172.21.204.201:26266 laddr=172.21.204.201:6379 fd=18 name= age=0 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=40928 argv-mem=10 obl=0 oll=0 omem=0 tot-mem=61466 events=r cmd=client user=default redir=-1
(上百个类似连接)

诊断:IP 10.0.1.23 的大量连接idle=0且执行简单ping,表明存在代码BUG或连接池配置错误。

3.3. 客户端入流量统计方法

方法一:使用Redis内置指标(基础估算)

Redis的client list命令提供了每个客户端的输入缓冲区信息:

# 提取客户端输入缓冲区信息
redis-cli client list | awk '
# 1. 解析 client list 输出,提取 IP、omem、tot-mem、argv-mem
{
    # 初始化变量
    ip = ""; omem = 0; tot_mem = 0; argv_mem = 0;
    # 遍历每个字段(格式:key=value)
    for (i=1; i<=NF; i++) {
        split($i, kv, "=");  # 分割 key 和 value(如 "addr=172.21.204.200:46102" → kv[1]="addr", kv[2]="172.21.204.200:46102"if (kv[1] == "addr") {
            split(kv[2], addr, ":");  # 提取 IP(去掉端口,如 "172.21.204.200:46102" → addr[1]="172.21.204.200")
            ip = addr[1];
        } else if (kv[1] == "omem") {
            omem = kv[2];
        } else if (kv[1] == "tot-mem") {
            tot_mem = kv[2];
        } else if (kv[1] == "argv-mem") {
            argv_mem = kv[2];
        }
    }
    # 按 IP 分组累加(存储为字节)
    sum_omem[ip] += omem;
    sum_tot_mem[ip] += tot_mem;
    sum_argv_mem[ip] += argv_mem;
    # 统计每个 IP 的连接数
    conn_count[ip]++;
}

# 2. 处理完所有行后,格式化输出结果
END {
    # 打印表头(左对齐,占20字符)
    printf "%-20s %-8s %-20s %-20s %-20s\n", 
           "客户端IP", "连接数", "omem总和(MB)", "tot-mem总和(MB)", "argv-mem总和(MB)";
    printf "%-20s %-8s %-20s %-20s %-20s\n", 
           "--------", "--------", "------------", "--------------", "--------------";
    
    # 遍历所有 IP,输出统计结果(字节转 MB:除以 1024*1024,保留2位小数)
    for (ip in sum_omem) {
        omem_mb = sum_omem[ip] / (1024*1024);
        tot_mem_mb = sum_tot_mem[ip] / (1024*1024);
        argv_mem_mb = sum_argv_mem[ip] / (1024*1024);
        printf "%-20s %-8d %.2f               %.2f               %.6f\n", 
               ip, conn_count[ip], omem_mb, tot_mem_mb, argv_mem_mb;
    }
}
'

示例输出:

客户端IP                连接数      omem总和(MB)           tot-mem总和(MB)        argv-mem总和(MB)      
--------             -------- ------------         --------------       --------------      
172.21.204.200       10       108.00               108.20               0.000000
127.0.0.1            1        0.00               0.06               0.000010

分析:显示每个客户端的输入缓冲区大小,可以间接反映流量大小。

方法二:使用系统级网络监控(推荐)

使用iftop工具按IP监控实时网络流量:

# 安装 iftop
sudo apt install iftop

# 监控Redis端口流量,按源IP分组
sudo iftop -P -N -n -i eth0 -f "port 6379" -F 192.168.1.100/32

示例输出:

interface: eth0
IP address: 192.168.1.100
MAC address: 00:1a:2b:3c:4d:5e
Listening on Redis port 6379

15:30:01 - 15:30:31   # 30秒流量统计
Source IP            =>           Redis Server       Traffic
10.0.1.23            =>           192.168.1.100      4.2Mb/s
10.0.5.67            =>           192.168.1.100      1.8Mb/s
10.0.3.45            =>           192.168.1.100      0.5Mb/s
方法三:使用tcpdump深度分析(精准测量)
# 捕获指定客户端IP的Redis流量
sudo tcpdump -i eth0 -s 0 -w redis_traffic.pcap host 10.0.1.23 and port 6379

# 分析捕获的数据包大小
sudo tcpdump -nn -r redis_traffic.pcap -w - | awk '{print $3}' | 
  grep '10.0.1.23' | 
  awk -F. '{print $1"."$2"."$3"."$4}' | 
  sort | uniq -c | sort -nr

示例输出:

# 显示每个客户端发送的数据包数量
  12542 10.0.1.23
   3845 10.0.5.67
   1298 10.0.3.45
方法四:使用Prometheus+Redis Exporter(长期监控)

如果已部署监控系统,可以配置以下查询:

promql
# 查询各客户端入流量排名
topk(10, rate(redis_net_input_bytes_total{instance="redis-cluster"}[5m]))

3.4. 分析慢查询(识别低效操作)

命令:

redis-cli -h 192.168.1.100 -p 6379 -a yourpassword slowlog get 5

示例输出(大Key问题):

1) 1) (integer) 145787
   2) (integer) 1645678901
   3) (integer) 12543
   4) 1) "HGETALL"
      2) "product:inventory:store:002"
   5) "10.0.3.45:57218"

诊断:IP 10.0.3.45 执行HGETALL耗时12.5秒,大HashKey导致阻塞。


4. 总结与行动指南

4.1 发现的问题类型

  1. 代码BUG型:某IP产生大量无效请求(如频繁ping)

  2. 热Key访问型:单一Key被超高并发访问

  3. 大Key阻塞型:单个大Value操作耗时过长

  4. 流量异常型:特定客户端发送过量请求

4.2 立即行动方案

  1. 精准流量分析:使用iftoptcpdump确认10.0.1.23的异常流量

  2. 紧急重启:重启异常IP(如10.0.1.23)上的服务

  3. 临时限流:使用iptables对异常IP进行流量限制

    # 限制单个IP的入流量为1Mb/s
    sudo iptables -A INPUT -p tcp -s 10.0.1.23 --dport 6379 -m limit --limit 1mb/s -j ACCEPT

4.3 长期治理策略

  1. 实施流量监控:

    • 部署Prometheus监控各客户端Redis流量

    • 设置客户端级流量告警阈值

  2. 架构优化:

    • 为不同服务创建独立的Redis实例

    • 实施客户端级速率限制(使用Redis模块或代理中间件)

  3. 流量分析与优化:

    # 定期生成客户端流量报告
    sudo iftop -t -P -N -n -i eth0 -f "port 6379" -F 192.168.1.100/32 -s 3600 > redis_traffic_report.txt

通过以上系统化的排查和流量统计方法,您不仅可以快速定位Redis流量激增的根本原因,还能精准识别问题客户端并采取有效措施恢复服务稳定性。

 
 
 
 
 posted on 2025-09-05 16:17  xibuhaohao  阅读(6)  评论(0)    收藏  举报