判断 Redis 性能瓶颈:CPU、内存还是网络?
三种常见瓶颈
Redis 的性能瓶颈通常来自三个方面:CPU、内存、网络。不同瓶颈有不同的症状和解决方案。准确地判断瓶颈类型是优化的第一步。
瓶颈判断流程图
Redis 响应变慢?
│
├─ CPU 使用率 > 80%?─── 是 ───→ CPU 瓶颈
│ ├─ 单线程 CPU 跑满
│ └─ Fork 进程占 CPU
│
├─ 内存使用率 > 80% 且 碎片率高?─── 是 → 内存瓶颈
│ ├─ 内存不足 → 淘汰/swap
│ └─ 碎片严重 → 内存浪费
│
├─ 带宽使用率接近上限?─── 是 → 网络瓶颈 → 提升带宽或限流
│
└─ 无明显资源瓶颈? → 其他原因
├─ 慢命令(BigKey)
├─ 过期 key 清理
└─ 主从同步延迟
详细判断方法
1. CPU 瓶颈判断
使用 top 命令观察:
# 查看 Redis 进程 CPU 使用
top -p $(pgrep -x redis-server)
# Redis 单线程,CPU 使用率 = 100% × CPU 核心数
# 如 4 核服务器,Redis 最多用 100% 算满
使用 INFO CPU:
redis-cli INFO CPU | grep used_cpu_sys
redis-cli INFO CPU | grep used_cpu_user
# 计算前后差值(采样间隔),如果 user+sys 时间/真实时间接近 1
# 说明 CPU 是瓶颈
CPU 瓶颈判断指标:
import time
def is_cpu_bottleneck(r):
"""判断是否 CPU 瓶颈"""
info1 = r.info('cpu')
time.sleep(5)
info2 = r.info('cpu')
cpu_sec = (info2['used_cpu_sys'] - info1['used_cpu_sys']) + \
(info2['used_cpu_user'] - info1['used_cpu_user'])
# CPU 利用率 = cpu_sec / 5 (采样间隔)
cpu_usage = cpu_sec / 5
return cpu_usage > 0.8 # 大于 80% 视为 CPU 瓶颈
CPU 瓶颈的症状:
– QPS 无法提升,达到上限(与服务器性能相关)
– top 显示 Redis 进程 CPU 占用接近 100%
– 延迟抖动但无明显慢查询
– 增加并发数不能提升吞吐量
2. 内存瓶颈判断
关键指标:
redis-cli INFO MEMORY
# 1. used_memory → 接近 maxmemory?
# 2. mem_fragmentation_ratio → 过高?
# 3. evicted_keys → > 0 表示正在淘汰
memory 瓶颈判断:
def is_memory_bottleneck(r):
info = r.info('memory')
used = info['used_memory']
maxmem = info['maxmemory']
evicted = info['evicted_keys']
frag = info['mem_fragmentation_ratio']
# 内存使用率 > 80%
memory_high = (used / maxmem) > 0.8 if maxmem > 0 else False
# 有淘汰发生
has_eviction = evicted > 0
# 碎片率过高
high_frag = frag > 2.0
return memory_high or has_eviction or high_frag
内存瓶颈的症状:
– 日志中出现 Can't save in background: fork: Cannot allocate memory
– QPS 下降伴随大量过期 key 淘汰
– 磁盘 IO 高(正在 swap)
– 内存碎片率 > 1.5 或 < 1.0
3. 网络瓶颈判断
使用网络工具:
# 查看网络带宽
sar -n DEV 2 5
# IFACE rxpck/s txpck/s rxkB/s txkB/s
# eth0 50000.00 50000.00 6250.00 6250.00
# 千兆网卡上限约 125MB/s
# 查看是否有丢包
netstat -s | grep -i "drop\|overflow\|retransmit"
网络瓶颈判断:
def is_network_bottleneck(r, bandwidth_mbps=1000):
"""判断是否网络瓶颈"""
info = r.info('stats')
input_kbps = info['instantaneous_input_kbps']
output_kbps = info['instantaneous_output_kbps']
total_kbps = input_kbps + output_kbps
total_mbps = total_kbps / 1000
return total_mbps > bandwidth_mbps * 0.8 # 超过 80% 带宽
网络瓶颈的症状:
– QPS 不高但响应慢
– 单次 bigkey 操作后延迟飙高
– 客户端报 connection timeout
– 带宽监控显示接近上限
4. 其他瓶颈信号
磁盘 I/O 瓶颈(持久化时):
# 查看磁盘 IO 情况
iostat -x 2 5 | grep -E "sd|nvme"
# %util 接近 100% 说明磁盘是瓶颈
命令延迟瓶颈:
# 查看命令耗时分布
redis-cli INFO COMMANDSTATS
# 输出示例
cmdstat_set:calls=100000,usec=500000,usec_per_call=5.00
cmdstat_get:calls=200000,usec=800000,usec_per_call=4.00
cmdstat_keys:calls=10,usec=5000000,usec_per_call=500000.00
# ↑ KEYS 命令平均 500ms!严重问题
实战判断流程
def diagnose_redis(r):
"""Redis 瓶颈诊断"""
print("=" * 50)
print("Redis 瓶颈诊断报告")
print("=" * 50)
info = r.info('server')
print(f"版本: {info['redis_version']}")
# 1. CPU 检查
cpu_info = r.info('cpu')
qps = r.info('stats')['instantaneous_ops_per_sec']
print(f"\n1. CPU 状态:")
print(f" 当前 QPS: {qps}")
if qps > 50000:
print(f" 高负载,注意 CPU 可能成为瓶颈")
# 2. 内存检查
mem = r.info('memory')
max_mem = mem['maxmemory']
used = mem['used_memory']
pct = used / max_mem * 100 if max_mem else 0
print(f"\n2. 内存状态:")
print(f" 使用: {used/1024/1024:.0f}MB / {max_mem/1024/1024:.0f}MB ({pct:.0f}%)")
print(f" 碎片率: {mem['mem_fragmentation_ratio']:.2f}")
print(f" 淘汰数: {mem['evicted_keys']}")
if pct > 80:
print(f" ⚠️ 内存使用率过高")
# 3. 慢查询检查
slow = r.slowlog_get(5)
if slow:
print(f"\n3. 最近慢查询:")
for s in slow:
cmd = ' '.join(s['command'].decode().split()[:3])
dur = s['duration'] / 1000
print(f" {dur:.1f}ms - {cmd}")
else:
print(f"\n3. 慢查询: 无")
# 4. 连接检查
clients = r.info('clients')
print(f"\n4. 连接状态:")
print(f" 当前连接: {clients['connected_clients']}")
print(f" 拒绝连接: {clients['rejected_connections']}")
return "诊断完成"
各瓶颈对应的解决方案
| 瓶颈类型 | 解决方案 |
|---|---|
| CPU 瓶颈 | 升级 CPU/使用 Redis Cluster/读分离 |
| 内存瓶颈 | 扩容/优化数据结构/设置合理淘汰策略 |
| 网络瓶颈 | 升级带宽/压缩数据/就近部署 |
| 磁盘 I/O | 使用 SSD/调整持久化策略 |
| 命令瓶颈 | 优化慢查询/避免 BigKey |
面试要点
- CPU 瓶颈的信号:Redis 进程 CPU > 80%、QPS 无法继续提升
- 内存瓶颈的信号:used_memory 接近 maxmemory、evicted_keys > 0、碎片率异常
- 网络瓶颈的信号:带宽使用率 > 80%、单次大操作后延迟飙高
- 使用 INFO 命令 加外部监控(top、iostat、sar)综合判断
- 启动时确保关闭 THP、调整 overcommit 等内核参数
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END


暂无评论内容