跳到主要内容

Redis 线上问题排查

问题

Redis 出现响应变慢、内存暴涨、连接数飙升等线上问题,如何排查?

答案

一、常见问题全景

二、大 Key 问题

什么是大 Key

类型大 Key 标准风险
String> 1MB网络阻塞
Hash> 5000 field操作耗时
List> 10000 元素DEL 阻塞
Set> 10000 成员SMEMBERS 卡顿
ZSet> 10000 成员ZRANGEBYSCORE 慢

发现大 Key

# 方法 1:redis-cli 扫描(安全,不阻塞)
redis-cli --bigkeys

# 方法 2:MEMORY USAGE 查看单个 Key
redis-cli MEMORY USAGE my_big_key

# 方法 3:SCAN + 检测(生产环境推荐)
redis-cli --scan --pattern '*' | while read key; do
size=$(redis-cli MEMORY USAGE "$key" 2>/dev/null)
if [ "$size" -gt 1048576 ]; then # > 1MB
echo "$key: $size bytes"
fi
done

处理大 Key

// ❌ 直接删除大 Key 可能阻塞 Redis
await redis.del('big_hash_key'); // Hash 有 10 万 field,DEL 耗时数秒

// ✅ 方案 1:UNLINK 异步删除(Redis 4.0+)
await redis.unlink('big_hash_key');

// ✅ 方案 2:分步渐进删除
async function deleteHashProgressively(key: string) {
let cursor = '0';
do {
const [nextCursor, fields] = await redis.hscan(key, cursor, 'COUNT', 100);
cursor = nextCursor;
if (fields.length > 0) {
const fieldNames = fields.filter((_, i) => i % 2 === 0);
await redis.hdel(key, ...fieldNames);
}
} while (cursor !== '0');
await redis.del(key); // 最后删除空 Key
}

三、热 Key 问题

热 Key = 大量请求集中在少数 Key 上,导致单节点压力过大。

发现方式:
1. redis-cli --hotkeys(需开启 LFU 策略)
2. 业务监控:统计 Redis 客户端各 Key 的访问频次
3. 代理层统计:Redis Proxy 统计 QPS 分布

解决方案

方案做法适用
本地缓存L1 缓存热 Key,短 TTL读多写少
Key 分片key:shard:0~9,随机读读多写少
读写分离从库分担读流量集群模式

四、慢命令排查

# 查看慢日志
redis-cli SLOWLOG GET 10

# 设置慢查询阈值(微秒)
redis-cli CONFIG SET slowlog-log-slower-than 10000 # 10ms
redis-cli CONFIG SET slowlog-max-len 128

常见慢命令

命令风险替代方案
KEYS *全量扫描 O(N)SCAN 渐进式遍历
SMEMBERS大 Set 全量返回SSCAN 分批
HGETALL大 Hash 全量返回HSCANHMGET 指定字段
DEL 大 Key阻塞主线程UNLINK 异步删除
FLUSHDB清空整个库FLUSHDB ASYNC

五、内存问题排查

# 查看内存使用
redis-cli INFO memory

# 关键指标
# used_memory : 已用内存
# used_memory_rss : 操作系统分配内存(含碎片)
# mem_fragmentation_ratio: 碎片率(> 1.5 需关注)
# maxmemory : 最大内存限制
问题表现解决
未设过期内存持续增长设置 TTL
碎片率高RSS > used × 1.5MEMORY PURGE 或重启
淘汰频繁evicted_keys 增长扩容或优化数据结构

六、持久化导致的卡顿

问题:RDB fork 子进程时,主进程短暂阻塞

原因:
- fork 需要复制页表,内存越大耗时越长
- 开启 AOF always 模式时,每次写入同步磁盘

解决:
1. 控制单实例内存 < 10GB
2. AOF 使用 everysec 策略(非 always)
3. 关闭 THP(Transparent Huge Pages)
4. 使用 SSD 磁盘

常见面试问题

Q1: Redis 为什么变慢了?排查思路是什么?

答案

排查顺序:
1. SLOWLOG GET → 有没有慢命令?
2. INFO memory → 内存是否达到上限?在淘汰?
3. INFO clients → 连接数是否异常?
4. INFO persistence → 是否在做 RDB/AOF rewrite?
5. latency 命令 → 是否有延迟事件?
6. 网络排查 → 客户端到 Redis 的网络延迟
7. 大 Key 排查 → --bigkeys 扫描

Q2: Redis 内存满了会怎样?

答案

取决于 maxmemory-policy(淘汰策略):

策略行为
noeviction写入报错(默认)
allkeys-lru淘汰最久未使用的 Key
allkeys-lfu淘汰最少使用频次的 Key
volatile-lru仅淘汰有过期时间的 Key(LRU)
volatile-ttl淘汰 TTL 最短的 Key

推荐 allkeys-lfu:根据访问频率淘汰,更智能。

Q3: Redis Cluster 节点数据倾斜怎么办?

答案

  1. 发现redis-cli --cluster info 查看各节点 Key 数量和内存
  2. 原因
    • 大 Key 集中在某节点
    • Hash Tag 导致固定路由
    • 迁移不均匀
  3. 解决
    • 拆分大 Key
    • 合理使用 Hash Tag
    • CLUSTER REBALANCE 重新平衡
    • 手动迁移 Slot

相关链接