命令 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",
]);
注意:
- 参数都必须按 Redis 协议顺序组织。
- 返回值通常缺少友好的转换。
- Cluster 的
sendCommand()API 还需要路由信息。 - 优先升级客户端并使用正式 API,
sendCommand()是兼容出口。
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 注入,仍需限制键名长度、值大小和允许执行的命令。
实用技巧
- 先查 Redis 命令语义,再查 Node-Redis 参数形式。
- 对
null、空数组、0和false分别处理,它们可能代表完全不同的业务结果。 - 避免直接执行
KEYS *、FLUSHALL、FLUSHDB等高风险命令。 - 对管理类 API 使用独立权限账号,不让普通应用账号拥有危险命令权限。