Redis 常用命令速查:五种数据类型、过期、批量与危险命令清单

一、结论先给

Redis 用得好不好,看三件事:有没有设过期时间、有没有用 KEYS、有没有给危险命令改名。这三个占了线上 Redis 事故的绝大多数。

铁律 原因
所有缓存 key 必须设 TTL 不设就是内存泄漏,迟早 OOM
生产禁用 KEYS * 单线程阻塞,几百万 key 能卡死十几秒
FLUSHALL/FLUSHDB/KEYS/CONFIG 必须改名或禁用 误执行就是灾难
value 不要超过 10KB 大 key 是网络和内存的双重负担
批量操作用 pipeline / MGET 一条一条发,网络往返是主要耗时

👉 命令记不全查 Linux 命令速查;Redis 日志报错分析用 日志分析工具。

二、连接与基础

redis-cli -h 127.0.0.1 -p 6379 -a 密码
redis-cli -h 127.0.0.1 -p 6379 -a 密码 --no-auth-warning    # 去掉明文密码警告
redis-cli -n 1                      # 选 1 号库(默认 16 个库,编号 0-15)
redis-cli --scan --pattern 'user:*' # 安全遍历
redis-cli --bigkeys                 # 找大 key(运维必用)
redis-cli --hotkeys                 # 找热 key(需 maxmemory-policy 为 LFU)
redis-cli --latency                 # 延迟采样
redis-cli --stat                    # 实时状态
redis-cli -a pwd INFO | grep -E "used_memory_human|connected_clients|instantaneous_ops_per_sec"
PING                    -- PONG
SELECT 1                -- 切库(集群模式不支持)
DBSIZE                  -- 当前库 key 数
INFO server / memory / stats / replication / keyspace
CONFIG GET maxmemory
CONFIG GET maxmemory-policy
SLOWLOG GET 10          -- 慢命令(默认超过 10 毫秒记录)
SLOWLOG LEN
CLIENT LIST             -- 客户端连接
MONITOR                 -- ⚠️ 实时打印所有命令,线上别用,会打满输出且严重降性能

三、五种数据类型与适用场景

3.1 String(最常用)

SET k v                 -- 设值
SET k v EX 3600         -- 60 分钟后过期 ⭐常用
SET k v PX 5000         -- 毫秒
SETNX k v               -- 不存在才设(分布式锁基础)
SET k v NX EX 30        -- 原子:不存在才设 + 30 秒过期 ⭐分布式锁标准写法
SETEX k 3600 v          -- 设值并指定秒数
GETSET k v2             -- 设新值返回旧值

GET k
MGET k1 k2 k3           -- 批量取 ⭐比三次 GET 快得多
MSET k1 v1 k2 v2
INCR counter            -- +1(原子,计数器/限流)
INCRBY counter 10
DECR counter
APPEND k "more"
STRLEN k

EXPIRE k 3600           -- 设过期(秒)
PEXPIRE k 60000         -- 毫秒
TTL k                   -- 剩余秒数;-1 永不过期,-2 已不存在
PERSIST k               -- 去掉过期

典型场景:缓存对象 JSON、计数器、分布式锁、限流、Token。

3.2 Hash(对象字段,省内存)

HSET user:1 name afei age 30 city beijing
HGET user:1 name
HMGET user:1 name age
HGETALL user:1          -- ⚠️ 字段多时很慢,用 HSCAN
HKEYS user:1 / HVALS user:1
HLEN user:1
HINCRBY user:1 age 1
HEXISTS user:1 email
HDEL user:1 city
HSCAN user:1 0 COUNT 100    -- 安全遍历大 hash

典型场景:购物车(cart:userId → 商品id 数量)、用户属性、配置项。

Hash vs String 存对象:

方式 优点 缺点
String 存 JSON 一次取完、简单 改一个字段要整体覆盖
Hash 存字段 可单字段读写、更省内存(ziplist 编码) 字段上千时 HGETALL 要小心

3.3 List(队列、栈、时间线)

LPUSH queue a b c       -- 左边插入
RPUSH queue x           -- 右边插入
LPOP queue              -- 左边弹出
RPOP queue
BLPOP queue 30          -- 阻塞弹出,30 秒超时 ⭐消息队列常用
BRPOP queue 30
LRANGE queue 0 -1       -- ⚠️ 全量取,大列表会卡
LRANGE queue 0 9        -- 取前 10
LLEN queue
LTRIM queue 0 99        -- 只保留最近 100 条 ⭐做时间线
LINDEX queue 0
LREM queue 1 "a"        -- 删 1 个值为 a 的元素

典型场景:消息队列(LPUSH + BRPOP)、最新动态列表、限流滑动窗口。

⚠️ Redis 5.0 起有了 Stream,做消息队列比 List 更合适(支持消费组、ACK、持久化)。

3.4 Set(去重、集合运算)

SADD tags:1 java redis mysql
SMEMBERS tags:1         -- ⚠️ 大集合慢,用 SSCAN
SISMEMBER tags:1 java   -- 是否存在 ⭐
SCARD tags:1            -- 元素数
SREM tags:1 mysql
SPOP tags:1             -- 随机弹出
SRANDMEMBER tags:1 3    -- 随机取 3 个(不删)

SINTER set1 set2        -- 交集(共同好友)
SUNION set1 set2        -- 并集
SDIFF set1 set2         -- 差集
SINTERSTORE result set1 set2
SSCAN tags:1 0 COUNT 100

典型场景:标签、去重、共同好友、抽奖、签到(BitMap 更省)。

3.5 ZSet(有序集合,排行榜)

ZADD rank 100 "player1" 200 "player2"
ZRANGE rank 0 9 WITHSCORES        -- 分数升序前 10
ZREVRANGE rank 0 9 WITHSCORES     -- 降序前 10 ⭐排行榜
ZRANGEBYSCORE rank 100 200 WITHSCORES   -- 分数区间
ZSCORE rank player1               -- 查分数
ZRANK rank player1                -- 升序排名(从 0)
ZREVRANK rank player1             -- 降序排名 ⭐
ZINCRBY rank 10 player1           -- 加分
ZCARD rank                        -- 成员数
ZCOUNT rank 100 200               -- 区间内数量
ZREM rank player1
ZREMRANGEBYRANK rank 0 99         -- 删排名前 100(保留榜单长度)
ZREMRANGEBYSCORE rank 0 50        -- 删分数区间的

典型场景:排行榜、延迟队列(score 存执行时间)、优先级队列、时间窗口限流。

四、通用 key 操作(含高危)

KEYS user:*             -- ❌ 生产禁用!单线程全量遍历,数据量大时卡死
SCAN 0 MATCH user:* COUNT 100   -- ✅ 游标方式分批遍历
TYPE k                  -- key 类型
EXISTS k
DEL k1 k2
UNLINK k1 k2            -- ⭐异步删除,大 key 用这个不阻塞
RENAME k k2
RENAMENX k k2
DUMP k / RESTORE k 0 "..."   -- 迁移用
MOVE k 1
OBJECT ENCODING k       -- 看内部编码(ziplist/quicklist 等)
MEMORY USAGE k          -- key 占多少内存 ⭐排查大 key

SCAN 的正确用法(游标迭代,注意可能返回重复,要去重):

#!/usr/bin/env bash
cursor=0
while : ; do
  read -r cursor keys < <(redis-cli -a pwd SCAN $cursor MATCH 'user:*' COUNT 500 | head -1 >/dev/null; echo)
  # 实际用 redis-cli --scan 更简单
done
# 推荐直接用:
redis-cli -a pwd --scan --pattern 'user:*' | head -1000

五、批量操作与 pipeline

MGET k1 k2 k3 ...       -- 批量读
MSET k1 v1 k2 v2        -- 批量写

pipeline(把多条命令打包一次发,减少网络 RTT):

# 用 redis-cli 的 pipe 模式批量导入
cat <<'EOF' | redis-cli -a pwd --pipe
SET a 1
SET b 2
SET c 3
EOF

# 从文件批量删除
redis-cli -a pwd --scan --pattern 'tmp:*' | xargs -L 1000 redis-cli -a pwd UNLINK

各语言客户端都支持 pipeline,比如 Java:

List<Object> res = redisTemplate.executePipelined((RedisCallback<Object>) conn -> {
    for (String k : keys) conn.get(k.getBytes(StandardCharsets.UTF_8));
    return null;
});

⚠️ pipeline 不是原子操作,要原子请用 MULTI/EXEC 或 Lua 脚本。

六、Lua 脚本(原子复合操作)

EVAL "return redis.call('GET', KEYS[1])" 1 mykey

-- 原子扣减库存(不存在则返回 -1,不足返回 -2)
EVAL "
local stock = tonumber(redis.call('GET', KEYS[1]) or '-1')
if stock < 0 then return -1 end
if stock < tonumber(ARGV[1]) then return -2 end
redis.call('DECRBY', KEYS[1], ARGV[1])
return stock - tonumber(ARGV[1])
" 1 sku:1 1

Lua 里不要用 KEYS 命令、不要写长循环(会阻塞),脚本执行是原子的,这是它相对 pipeline 的核心优势。

七、过期策略与内存淘汰

Redis 删过期 key 用两种方式配合:

方式 说明
惰性删除 访问时才检查过期并删
定期删除 每 100ms 随机抽查一部分 key(默认每秒 10 次)

所以过期 key 不一定立刻释放内存,这是"设了 TTL 但内存还是涨"的原因之一。

内存到上限时的淘汰策略:

CONFIG GET maxmemory
CONFIG GET maxmemory-policy
CONFIG SET maxmemory 4gb
CONFIG SET maxmemory-policy allkeys-lru
策略 含义 适用
noeviction 不淘汰,写直接报错 默认;缓存场景千万不要用
allkeys-lru 全体 key 里淘汰最久未用 纯缓存首选
volatile-lru 只在设了 TTL 的 key 里淘汰 混合存储
allkeys-lfu 全体淘汰最少使用 有热点且长期稳定的场景
volatile-lfu 同上但限设了 TTL 的
allkeys-random 随机淘汰
volatile-ttl 淘汰剩余生存时间最短的

maxmemory 一定要设(建议物理内存的 60-70%),否则可能把机器内存吃光被 OOM。

八、危险命令:改名或禁用

在 redis.conf 里把这些命令改名成随机字符串,等于禁用:

rename-command FLUSHALL ""
rename-command FLUSHDB  ""
rename-command KEYS     "e8f3a1c9keys"
rename-command CONFIG   "b2d7f0config"
rename-command SHUTDOWN "a1c3e5shutdown"
rename-command DEBUG    ""
rename-command SAVE     ""      # 用 BGSAVE

"" 表示彻底禁用(执行时返回 unknown command)。

改名后运维脚本要同步改,或者用 redis-cli 时带上新名字。

九、常见误区

  1. 用 KEYS * 查有多少 key:生产环境一发就是事故,用 DBSIZE 或 SCAN。
  2. 缓存不设 TTL:内存只涨不降,最终写满触发淘汰或 OOM。
  3. 把 Redis 当数据库用且不开启持久化:重启数据全没。
  4. 大 key(几 MB 的 String、百万成员的 Set):删除、迁移、网络传输全都是坑,用 --bigkeys 定期扫。
  5. 一个 Redis 实例塞几百个业务:互相影响,一个业务的 KEYS 拖垮全部。
  6. DEL 删百万成员的集合:同步删除阻塞,要用 UNLINK(异步)。
  7. key 名太长:user:profile:detail:2026:09:23:1234567 这种,key 本身占的内存比 value 还多。

十、几条纪律

  1. 所有缓存 key 必设 TTL,且加随机抖动(防同一秒集体过期)。
  2. 生产禁用 KEYS,遍历一律 SCAN;FLUSHALL/CONFIG 改名。
  3. maxmemory 设为物理内存 60-70%,策略选 allkeys-lru(纯缓存)。
  4. 单个 value 控制在 10KB 以内;大集合拆分(如按用户 id 分桶)。
  5. 批量用 MGET/pipeline;复合操作要原子就用 Lua。
  6. 定期 redis-cli --bigkeys、--hotkeys 巡检,发现大 key 提前拆。
  7. 删除大 key 用 UNLINK 不用 DEL。

十一、延伸阅读

👉 相关在线工具:Linux 命令速查 · 日志分析,免登录、浏览器内处理。

还有 65 个免费在线工具

纯前端实现,不用注册,数据不上传服务器。

浏览全部工具