redis大key排查指南

文章目录

    • [一、什么是 Redis 大 Key?](#一、什么是 Redis 大 Key?)
    • [二、为什么要排查大 Key?](#二、为什么要排查大 Key?)
    • [三、如何排查 Redis 大 Key?](#三、如何排查 Redis 大 Key?)
      • [1、使用 Redis 自带的命令 bigkeys](#1、使用 Redis 自带的命令 bigkeys)
      • [2、使用 SCAN + MEMORY USAGE](#2、使用 SCAN + MEMORY USAGE)
    • [Redis 基本数据数据类型](#Redis 基本数据数据类型)
      • String(字符串)
      • [Hash(哈希)------ 类似一个小型的对象或 Map](#Hash(哈希)—— 类似一个小型的对象或 Map)
      • [List(列表)------ 有序、可重复元素(类似队列)](#List(列表)—— 有序、可重复元素(类似队列))
      • [Set(集合)------ 无序、去重元素](#Set(集合)—— 无序、去重元素)
      • [Sorted Set(有序集合)------ 集合 + 分数(score)](#Sorted Set(有序集合)—— 集合 + 分数(score))
      • [Bitmaps / HyperLogLog / GEO(高级场景)](#Bitmaps / HyperLogLog / GEO(高级场景))

一、什么是 Redis 大 Key?

大 key 是指:

  • 单个 key 本身的内容过大(如一个超长字符串、超长列表、集合等)

  • 或者一个集合类 key(如 hash、list、zset、set)中 元素数量过多

Redis 是单线程模型,一次性访问、删除大 key 可能阻塞主线程导致其他请求延迟。


常见的大 Key 类型

数据类型 表现形式
String 超大字符串,如缓存整页 HTML、全文数据等
List 超长队列,如上万条记录未消费
Hash 字段数量巨大,如几万个属性
Set/Sorted Set 包含大量成员

二、为什么要排查大 Key?

大 Key 会带来如下问题:

  • Redis 是单线程模型,操作大 Key 会阻塞其他请求,读取/写入大 Key 会拉长响应时间
  • 单个 Key 占用大量内存,影响缓存命中率
  • 影响客户端响应速度、增加网络传输负担
  • 批量删除大 Key 极易引发"雪崩效应"

三、如何排查 Redis 大 Key?

1、使用 Redis 自带的命令 bigkeys

bash 复制代码
redis-cli -h 113.44.85.42 -p 6379 -a root --bigkeys

2、使用 SCAN + MEMORY USAGE

SCAN:用来遍历 Redis 的 key 空间,相比 KEYS * 更安全(不会阻塞服务器)

你可以配合 MEMORY USAGE 写脚本,批量找出大于某阈值(如 1MB)的 key。

shell脚本(阈值 1KB):

复制代码
#!/bin/bash

# 配置部分
HOST=113.44.85.42
PORT=6379
PASSWORD="root"  # 如果有密码,填入;没有则留空
THRESHOLD=1024  # 阈值,单位字节
COUNT=1000      # 每次 SCAN 的数量

# 设置 redis-cli 命令前缀,重定向 stderr(过滤警告)
REDIS_CLI="redis-cli -h $HOST -p $PORT"
if [[ -n "$PASSWORD" ]]; then
  REDIS_CLI="$REDIS_CLI -a $PASSWORD"
fi
REDIS_CLI="$REDIS_CLI 2>/dev/null"

# 初始化游标
cursor=0

echo "🔍 正在扫描 Redis 中超过 $((THRESHOLD / 1024)) KB 的大 Key..."

# 扫描循环
while :
do
  result=$(eval "$REDIS_CLI SCAN $cursor COUNT $COUNT")
  cursor=$(echo "$result" | head -n 1)
  keys=$(echo "$result" | tail -n +2)

  for key in $keys
  do
    size=$(eval "$REDIS_CLI MEMORY USAGE \"$key\"")
    if [[ "$size" -ge "$THRESHOLD" ]]; then
      size_kb=$(awk "BEGIN { printf \"%.2f\", $size/1024 }")
      echo "🔥 $key -> ${size_kb} KB"
    fi
  done

  if [[ "$cursor" == "0" ]]; then
    echo "✅ 扫描完毕。"
    break
  fi
done

效果:

Redis 基本数据数据类型

String(字符串)

示例命令:

bash 复制代码
SET username "chen123"
GET username
INCR counter
DECR counter
SETEX session:token 3600 "abcdefg"  # 带过期时间

场景举例:

  • 缓存用户昵称、令牌
  • 存储计数器(如访问次数)

Hash(哈希)------ 类似一个小型的对象或 Map

示例命令:

bash 复制代码
HSET user:1001 name "Alice" age "25"
HGET user:1001 name
HGETALL user:1001
HINCRBY user:1001 age 1

场景举例:

  • 存储用户信息、商品信息等结构化数据
  • 适合表示对象属性

List(列表)------ 有序、可重复元素(类似队列)

示例命令:

bash 复制代码
LPUSH queue "task1"
LPUSH queue "task2"
RPOP queue   # 出队
LRANGE queue 0 -1

场景举例:

  • 实现消息队列、任务列表
  • 最近浏览记录(滚动窗口)

Set(集合)------ 无序、去重元素

示例命令:

bash 复制代码
SADD tags "java" "redis" "backend"
SISMEMBER tags "java"
SMEMBERS tags
SREM tags "java"

场景举例:

  • 存用户兴趣标签、文章标签
  • 用户去重签到等

Sorted Set(有序集合)------ 集合 + 分数(score)

示例命令:

bash 复制代码
ZADD leaderboard 100 "player1"
ZADD leaderboard 200 "player2"
ZRANGE leaderboard 0 -1 WITHSCORES  # 升序
ZREVRANGE leaderboard 0 1 WITHSCORES  # 前2名(降序)
ZINCRBY leaderboard 50 "player1"

场景举例:

  • 排行榜(积分榜、点赞榜)
  • 优先级队列(score 表示权重)

Bitmaps / HyperLogLog / GEO(高级场景)

  • Bitmaps:用户签到、活跃状态
  • HyperLogLog:高效统计去重(如 UV)
  • GEO:地理位置查询,附近的人功能

❤觉得有用的可以留个关注~❤

相关推荐
影子tec2 分钟前
thinkphp6 + oracle 数据库连接 表名、字段名大小写和字符集
数据库·oracle·php
qq_4255028516 分钟前
SQL Server 高可用集群(AOHA)数据库故障恢复
数据库·sqlserver·aoha·sql server高可用群集
其实你热情似火19 分钟前
Java基础第20天-JDBC
java·数据库·oracle
观无34 分钟前
基于AOP+Log4Net+AutoFac日志框架
java·大数据·数据库
洛神灬殇42 分钟前
【Redis技术进阶之路】「原理分析系列开篇」探索事件驱动枚型与数据特久化原理实现(时间事件驱动执行控制)
redis·后端
没逻辑1 小时前
👀 Redis 实时调优与监控实践:基于 MONITOR、INFO、SLOWLOG
redis
艺杯羹1 小时前
JDBC 初认识、速了解
java·数据库·jdbc
没逻辑1 小时前
⏰ Redis 在支付系统中作为延迟任务队列的实践
redis·后端
脑子慢且灵2 小时前
MySQL:存储函数和存储过程
数据库·mysql·oracle·存储过程·存储函数
是大强2 小时前
mongodb 远程访问
数据库·mongodb