命令 API、返回值与二进制数据

Node-Redis 为标准 Redis 命令提供了两种常见命名:原始大写命令和更符合 JavaScript 习惯的 camelCase 命令。

await client.HSET("nloop:user:42", "name", "Alice");
await client.hSet("nloop:user:42", "name", "Alice");

教程统一使用 camelCase,便于阅读。

命令修饰符使用对象

Redis CLI 中的命令:

SET lock:order-1 token NX EX 30

Node-Redis 中写成:

await client.set("lock:order-1", "token", {
  NX: true,
  EX: 30,
});

这种对象形式减少参数顺序错误,并能获得 TypeScript 自动补全。

返回值会被转换

const result: Record<string, string> = await client.hGetAll("nloop:user:42");

Redis 协议原始响应可能是扁平数组,但 Node-Redis 会将 HGETALL 转换成更方便的对象。不同命令的返回类型不同,应让编辑器帮助你检查,而不是假设所有响应都是字符串。

使用 sendCommand()

当服务端出现新命令,而当前 Node-Redis 版本尚未封装时,可发送原始命令:

const reply: unknown = await client.sendCommand([
  "SET",
  "nloop:feature:key",
  "value",
  "NX",
]);

注意:

Buffer 与类型映射

普通文本默认返回字符串。如果命令返回序列化后的二进制内容,例如 DUMP,必须保留为 Buffer:

import { createClient, RESP_TYPES } from "redis";

const binaryClient = createClient().withTypeMapping({
  [RESP_TYPES.BLOB_STRING]: Buffer,
});

binaryClient.on("error", (error: Error) => {
  console.error(error);
});

await binaryClient.connect();

try {
  const dump: Buffer | null = await binaryClient.dump("source-key");

  if (dump !== null) {
    await binaryClient.restore("destination-key", 0, dump, {
      REPLACE: true,
    });
  }
} finally {
  await binaryClient.close();
}

不要把任意二进制响应先转成 UTF-8 字符串,否则可能破坏内容。

避免命令注入式思维

Node-Redis 发送的是参数数组,不是拼接一整段 Redis CLI 文本。正确做法:

await client.set(userProvidedKey, userProvidedValue);

不要为了“动态命令”把用户输入拼成一段字符串再自行拆分。即便没有传统 SQL 注入,仍需限制键名长度、值大小和允许执行的命令。

实用技巧