ITADN
redis/node-redis
README.md
以下内容由 AI 翻译,如有问题请点此提交 issue 反馈

Node-Redis

Tests Coverage License

Discord Twitch YouTube Twitter

node-redis 是一个现代、高性能的 Redis 的 Node.js 客户端。

如何开始使用 Redis?

在 Redis University 免费学习

使用 Redis Launchpad 加速构建

试用 Redis Cloud

深入开发者教程

加入 Redis 社区

在 Redis 工作

安装

通过 docker 启动一个 redis:

docker run -p 6379:6379 -d redis:8.0-rc1

要安装 node-redis,只需:

npm install redis

"redis" 是包含所有其他包的"一体化"包。如果你只需要部分命令, 可以单独安装相应的包。参见以下列表。

名称描述
redis包含所有 "redis-stack" 模块的客户端
@redis/client基础客户端(即 RedisClientRedisCluster 等)
@redis/bloomRedis Bloom 命令
@redis/jsonRedis JSON 命令
@redis/searchRediSearch 命令
@redis/time-seriesRedis Time-Series 命令
@redis/entraid使用 Microsoft Entra ID 为 Redis 客户端提供基于令牌的安全身份验证

正在寻找用于处理对象映射的高级库? 参见 redis-om-node

用法

基本示例

import { createClient } from "redis";

const client = await createClient()
  .on("error", (err) => console.log("Redis Client Error", err))
  .connect();

await client.set("key", "value");
const value = await client.get("key");
console.log(value); // 'value'
client.destroy();

相同的示例在 CommonJS 中(例如 node example.jspackage.json 中没有 "type": "module"):

const { createClient } = require("redis");

async function main() {
  const client = await createClient()
    .on("error", (err) => console.log("Redis Client Error", err))
    .connect();

  await client.set("key", "value");
  const value = await client.get("key");
  console.log(value); // 'value'
  client.destroy();
}

main().catch(console.error);

上述代码连接到 localhost 的 6379 端口。要连接到不同的主机或端口,请使用格式为 redis[s]://[[username][:password]@][host][:port][/db-number] 的连接字符串:

createClient({
  url: "redis://alice:foobared@awesome.redis.server:6380",
});

您还可以使用离散参数、UNIX 套接字,甚至 TLS 进行连接。详细信息请参阅 客户端配置指南

要检查客户端是否已连接并准备好发送命令,请使用 client.isReady,它将返回一个布尔值。 client.isOpen 也可用。当客户端的底层套接字打开时,它返回 true,当套接字未打开时 (例如,当客户端仍在连接或在网络错误后重新连接时),它返回 false

Redis 命令

内置支持所有 开箱即用的 Redis 命令。它们通过原始的 Redis 命令名称(HSETHGETALL 等) 以及更友好的驼峰式命名版本(hSethGetAll 等)暴露:

// raw Redis commands
await client.HSET("key", "field", "value");
await client.HGETALL("key");

// friendly JavaScript commands
await client.hSet("key", "field", "value");
await client.hGetAll("key");

命令的修饰符使用 JavaScript 对象指定:

await client.set("key", "value", {
  EX: 10,
  NX: true,
});

回复将被转换为有用的数据结构:

await client.hGetAll("key"); // { field1: 'value1', field2: 'value2' }
await client.hVals("key"); // ['value1', 'value2']

Buffers 同样受支持:

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

await client.hSet("key", "field", Buffer.from("value")); // 'OK'
await client.hGet("key", "field"); // { field: <Buffer 76 61 6c 75 65> }

对于返回序列化二进制负载的命令,例如 DUMP,在使用诸如 RESTORE 等命令处理结果之前,请将 blob 字符串映射为 Buffer

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

const dump = await binaryClient.dump("source");
await binaryClient.restore("destination", 0, dump);

不支持的 Redis 命令

如果你想执行 Node Redis 尚不识别的命令和/或使用参数(目前!),请使用 .sendCommand()

await client.sendCommand(["SET", "key", "value", "NX"]); // 'OK'

await client.sendCommand(["HGETALL", "key"]); // ['key1', 'field1', 'key2', 'field2']

注意:使用集群时,API 有所不同

事务 (Multi/Exec)

通过调用 .multi() 来开始一个 事务,然后链式调用你的命令。当你 完成后,调用 .exec(),你将得到一个包含结果的数组:

await client.set("another-key", "another-value");

const [setKeyReply, otherKeyValue] = await client
  .multi()
  .set("key", "value")
  .get("another-key")
  .exec(); // ['OK', 'another-value']

你还可以通过调用 .watch()监视 键。如果任何被监视的键发生变化,你的事务将会中止。

阻塞命令

在 v4 中,RedisClient 能够在“主” 连接之上使用“隔离池”来创建连接池。然而,没有方法可以在没有“主”连接的情况下使用该池:

const client = await createClient()
  .on("error", (err) => console.error(err))
  .connect();

await client.ping(client.commandOptions({ isolated: true }));

在 v5 中,我们将此池逻辑提取到了其自身的类中——RedisClientPool

const pool = await createClientPool()
  .on("error", (err) => console.error(err))
  .connect();

await pool.ping();

Pub/Sub

参见 Pub/Sub 概述

Scan Iterator

SCAN 的结果可以使用 async iterators 进行遍历:

for await (const keys of client.scanIterator()) {
  console.log(keys, await client.mGet(keys));
}

这在 HSCANSSCANZSCAN 中同样适用:

for await (const { field, value } of client.hScanIterator("hash")) {
}
for await (const member of client.sScanIterator("set")) {
}
for await (const { score, value } of client.zScanIterator("sorted-set")) {
}

您可以通过提供配置对象来覆盖默认选项:

client.scanIterator({
  TYPE: "string", // `SCAN` only
  MATCH: "pattern*",
  COUNT: 100,
});

比较并设置/删除 (CAS/CAD)

注意: CAS/CAD 操作在 Redis 8.4 中引入

// Conditionally update only if the current value matches
await client.set("key", "new-value", { condition: "IFEQ", matchValue: "old-value" });

// Conditionally delete only if the current value matches
await client.delEx("key", { condition: "IFEQ", matchValue: "expected-value" });

本地摘要

注意:此功能需要可选的 @node-rs/xxhash 对等依赖。

digest 辅助函数在本地计算 XXH3 64 位哈希,与 Redis 通过 DIGEST 命令计算的结果一致。这在处理大值的 CAS/CAD 操作中非常有用,因为比较完整值会效率低下。

npm install @node-rs/xxhash
import { digest } from "redis";

const hash = await digest("my-value");

await client.set("key", "new-value", { condition: "IFDEQ", matchValue: hash });

断开连接

QUIT 命令在 Redis 7.2 中已被弃用,在 Node-Redis 中也应视为已弃用。客户端无需再向服务器发送 QUIT 命令,只需直接关闭网络连接即可。

client.QUIT/quit() 已被 client.close() 取代。此外,为避免混淆,client.disconnect() 已重命名为 client.destroy()

client.destroy();

客户端缓存

Node Redis v5 增加了对 客户端缓存 的支持,该功能允许客户端在本地缓存查询结果。当缓存的结果不再有效时,Redis 服务器会通知客户端。

// Enable client side caching with RESP3
const client = createClient({
  RESP: 3,
  clientSideCache: {
    ttl: 0,             // Time-to-live (0 = no expiration)
    maxEntries: 0,      // Maximum entries (0 = unlimited)
    evictPolicy: "LRU"  // Eviction policy: "LRU" or "FIFO"
  }
});

请参阅 V5 文档 以获取更多详细信息和高级用法。

自动管道化

Node Redis 会自动将同一 "tick" 期间发出的请求进行管道化处理。

client.set("Tm9kZSBSZWRpcw==", "users:1");
client.sAdd("users:1:tokens", "Tm9kZSBSZWRpcw==");

当然,如果你不对你的 Promises 做任何处理,你肯定会 遇到 未处理的 Promise 异常。要利用 自动流水线并处理你的 Promises,请使用 Promise.all()

await Promise.all([
  client.set("Tm9kZSBSZWRpcw==", "users:1"),
  client.sAdd("users:1:tokens", "Tm9kZSBSZWRpcw=="),
]);

Sentinel

查看 sentinel 部分 以了解如何使用哨兵使用该库。

Programmability

参见 Programmability 概述

Clustering

使用 Node Redis 连接 Redis Cluster 时,请查阅 Clustering 指南

OpenTelemetry

OpenTelemetry Metrics Instrumentation

import { createClient, OpenTelemetry } from "redis";

OpenTelemetry.init({
  metrics: {
    enabled: true
  }
});

const client = createClient()

await client.connect();
// ... use the client as usual

重要: 初始化 OpenTelemetry 仅启用 node-redis 指标插桩,并且需要 @opentelemetry/api 以及在您的应用程序中配置的 OpenTelemetry SDK。

重要: 在创建 Redis 客户端之前初始化 OpenTelemetry。 有关 SDK/提供者/导出器的设置、验证和高级配置,请参阅:

Diagnostics Channel

Node Redis 通过 Node.js diagnostics_channel 发布遥测数据,使 APM 工具和自定义插桩能够观察命令、连接和内部事件。有关完整的通道参考和使用示例,请参阅 Diagnostics Channel 指南

Events

Node Redis 客户端类是一个 Nodejs EventEmitter,每次网络状态发生变化时都会发出一个事件:

名称触发时机监听器参数
connect发起与服务器的连接无参数
ready客户端已准备就绪无参数
end连接已关闭(通过 .close().destroy()无参数
error发生错误——通常是网络问题,例如 "Socket closed unexpectedly"(error: Error)
reconnecting客户端正在尝试重新连接到服务器无参数
sharded-channel-moved参见 此处参见 此处
invalidate客户端跟踪(Client Tracking)已启用 emitInvalidate 且某个键被失效(key: RedisItem | null)

:warning: 你必须监听 error 事件。如果客户端没有注册至少一个 error 监听器,并且 发生了 error,该错误将被抛出,Node.js 进程将退出。有关更多详细信息,请参阅 > EventEmitter 文档

客户端不会发出上述列表之外的任何其他事件

支持的 Redis 版本

Node Redis 支持以下版本的 Redis:

请参阅 支持的 Redis 版本

迁移

贡献

如果你想做出贡献,请查看贡献指南

感谢所有已经为 Node Redis 做出贡献的人!

Contributors

许可证

本仓库采用 "MIT" 许可证。参见 LICENSE.