跳至主要內容

常用命令 & 机制(对比 JS API)

Mr.Dingredis命令过期事务前端转后端大约 4 分钟约 1255 字

常用命令 & 机制(对比 JS API)

1. 过期时间(TTL)— ≈ setTimeout 自动删除

# 设置 key 的同时指定过期时间
SET code "9527" EX 300        # 300 秒后自动删除

# 单独设置过期
SET code "9527"
EXPIRE code 300               # 300 秒后过期

# 查看剩余时间
TTL code                     # → 267(还有 267 秒)
TTL code                     # → -1 表示永不过期
TTL code                     # → -2 表示 key 已不存在

# 移除过期时间
PERSIST code

# 设置过期时间(毫秒)
SET code "9527" PX 300000    # 300 秒(毫秒为单位)

# 更精准:过期时间戳
EXPIREAT code 1800000000     # 在指定时间戳过期
// JS 类比(手动实现)
const cache = new Map();

function setWithTTL(key, value, seconds) {
    cache.set(key, value);
    setTimeout(() => cache.delete(key), seconds * 1000);
}

实战场景

  • 验证码:5 分钟过期
  • Session:30 分钟无操作自动过期
  • 限流:1 秒内只允许 10 次请求(用 TTL 做滑动窗口)
  • 缓存:热点数据 1 小时失效

2. Key 命名规范与操作

# 命名惯例:对象类型:ID:字段
# 像 URL 路径一样组织

SET user:1:name "小明"         # 用户 ID 1 的名字
SET article:42:title "标题"    # 文章 ID 42 的标题

# 键空间操作(≈ Object.keys / Map.keys)
KEYS *                         # 查看所有 key(生产环境禁用!会卡死)
KEYS user:*                    # 查所有 user 前缀的 key

# 改用 SCAN(安全版本,分批遍历)
SCAN 0 MATCH user:* COUNT 100  # 分批扫描,不阻塞 Redis

# 判断 key 是否存在
EXISTS user:1:name             # → 1(存在)
EXISTS notexist                # → 0(不存在)

# 删除
DEL user:1:name

# 查看类型
TYPE user:1:name               # → string
TYPE user:1                    # → hash

# 查看剩余过期时间
TTL user:1:name

⚠️ 生产环境禁止用 KEYS *:会遍历所有 key,如果 key 数量很大(百万级)会阻塞 Redis 几秒钟!


3. 事务(对比 JS Promise.all + 回滚)

# Redis 事务:命令按顺序执行,不会被其他客户端打断
MULTI                         # 开始事务(类似 START TRANSACTION)
SET stock:1 10
DECR stock:1                  # 减少库存
EXEC                          # 执行(类似 COMMIT)

# 放弃事务
DISCARD                       # 类似 ROLLBACK

# 带条件的事务(乐观锁,类似前端 CAS 乐观更新)
WATCH stock:1                 # 监视 key
GET stock:1                   # 检查库存
# ... 如果 stock:1 被别的客户端改了,EXEC 会失败
MULTI
DECR stock:1
EXEC
# 如果执行期间 stock:1 被修改,EXEC 返回 nil(失败)
// JS 类比
// 普通事务 ≈ Promise.all(按顺序、互不打扰)
await Promise.all([cmd1, cmd2, cmd3]);

// WATCH ≈ 乐观锁(git push 前发现冲突)
async function decrStock(id) {
    const version = await getVersion(id);
    // 如果别人改了 version,下面的 update 会失败
    await update({ id, version: version + 1 });
}

对比 MySQL 事务

特性MySQLRedis
原子性✅ 全做或全不做❌ 某条失败,前面不自动回滚
隔离性多种隔离级别串行执行命令
回滚ROLLBACKDISCARD 仅放弃未执行的
复杂度简单

Redis 事务的特性:命令排着队按顺序执行,中间不插队。但不像 MySQL 那样某条失败就自动回滚。


4. Pipeline — 批量发送(≈ Promise.all 批量请求)

# 普通模式:发 3 条命令需要 3 次网络往返
SET a 1
GET a
INCR a

# Pipeline:一次性发送,一次性接收结果
# (N 条命令只需要 1 次网络往返)
// Node.js Pipeline 示例
const pipeline = redis.pipeline();
pipeline.set('a', 1);
pipeline.get('a');
pipeline.incr('a');
const results = await pipeline.exec();
// results → [[null, 'OK'], [null, '1'], [null, '2']]

前端理解:Pipeline ≈ HTTP/2 的多路复用,一次连接发多个请求,减少网络开销。批量操作性能提升 5~10 倍。


5. 分布式锁(前端没有的机制)

# 用 SETNX + 过期时间实现分布式锁
# SETNX = SET if Not eXists

# 加锁
SETNX lock:order:123 "server-A"   # 成功返回 1,失败返回 0
EXPIRE lock:order:123 10          # 避免死锁:10 秒自动释放

# Redis 2.8+ 一行搞定(加锁 + 过期原子操作)
SET lock:order:123 "server-A" NX EX 10

# 解锁
if GET lock:order:123 == "server-A"
    DEL lock:order:123
// JS 类比:用唯一 key 加锁
// 多人同时操作同一条数据时,只有第一个人能拿到锁

场景:秒杀库存、定时任务防重复执行、分布式系统资源互斥


6. 消息队列(List 实现)

# 生产者(≈ postMessage)
LPUSH msg:queue "任务1"        # 发消息

# 消费者(≈ 轮询接收)
BRPOP msg:queue 0             # 阻塞直到有消息(0 = 永远等待)
BRPOP msg:queue 30            # 阻塞最多 30 秒

# 多个消费者:一条消息只能被一个消费者取走
# 天然实现任务分发
// JS 类比
// 生产者
messageQueue.push('任务1');

// 消费者(阻塞式等待)
while (true) {
    const task = await waitForTask();  // 类似 BRPOP
    process(task);
}

命令速查表

场景命令说明
设置SET key val [EX/NX/XX]存值,可设过期、仅在不存在时设
读取GET key取值
删除DEL key删键
过期EXPIRE key sec设秒级过期
过期TTL key查剩余秒数
判断EXISTS key是否存在
类型TYPE key值类型
事务MULTI / EXEC开启/执行事务
批量Pipeline一次性发送多条(客户端功能)
SET NX EX原子性分布式锁
遍历SCAN cursor安全遍历所有 key
上次编辑于:
贡献者: dingyongya