Node-Redis
node-redis 是一个现代化、高性能的 Node.js Redis 客户端。
如何使用 Redis?
软件包
名称 | 描述 |
---|---|
redis | |
@redis/client | |
@redis/bloom | Redis Bloom 命令 |
@redis/graph | Redis Graph 命令 |
@redis/json | Redis JSON 命令 |
@redis/search | RediSearch 命令 |
@redis/time-series | Redis Time-Series 命令 |
:warning: 在 4.1.0 版本中,我们将子包从
@node-redis
移动到了@redis
。如果你只是使用npm install redis
,你不需要做任何改变——它会自动升级。如果你直接使用子包,你需要指向新的作用域(例如使用@redis/client
而不是@node-redis/client
)。
安装
通过 docker 启动 redis:
docker run -p 6379:6379 -it redis/redis-stack-server:latest
要安装 node-redis,只需:
npm install redis
:warning: 新接口简洁酷炫,但如果你有现有的代码库,你可能需要阅读迁移指南。
寻找处理对象映射的高级库?请参见 redis-om-node!
用法
基本示例
import { createClient } from 'redis';
const client = await createClient()
.on('error', err => console.log('Redis 客户端错误', err))
.connect();
await client.set('key', 'value');
const value = await client.get('key');
await client.disconnect();
上述代码连接到本地主机的 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 命令名称(HSET
、HGETALL
等)和更友好的驼峰式版本(hSet
、hGetAll
等)暴露:
// 原始 Redis 命令
await client.HSET('key', 'field', 'value');
await client.HGETALL('key');
// 友好的 JavaScript 命令
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']
也支持 Buffer
:
await client.hSet('key', 'field', Buffer.from('value')); // 'OK'
await client.hGetAll(
commandOptions({ returnBuffers: true }),
'key'
); // { field: <Buffer 76 61 6c 75 65> }
不支持的 Redis 命令
如果你想运行 Node Redis 尚不知道的命令和/或使用参数,请使用 .sendCommand()
:
await client.sendCommand(['SET', 'key', 'value', 'NX']); // 'OK'
await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2']
事务(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()
来监视键。如果任何被监视的键发生变化,你的事务将会中止。
要深入了解事务,请查看隔离执行指南。
阻塞命令
通过指定 isolated
选项,可以在新连接上运行任何命令。当命令的 Promise
被履行时,新创建的连接将被关闭。
这种模式特别适用于阻塞命令——比如 BLPOP
和 BLMOVE
:
import { commandOptions } from 'redis';
const blPopPromise = client.blPop(
commandOptions({ isolated: true }),
'key',
0
);
await client.lPush('key', ['1', '2']);
await blPopPromise; // '2'
要了解更多关于隔离执行的信息,请查看指南。
发布/订阅
请参阅发布/订阅概述。
扫描迭代器
for await (const key of client.scanIterator()) {
// 使用 key!
await client.get(key);
}
这也适用于 HSCAN
、SSCAN
和 ZSCAN
:
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`
MATCH: 'patter*',
COUNT: 100
});
可编程性
Redis 提供了一个编程接口,允许在 redis 服务器上执行代码。
函数
以下示例从 redis 中检索一个键,返回该键的值加上一个整数。例如,如果你的键 foo 的值为 17,我们运行 add('foo', 25)
,它会返回生命、宇宙和万物的答案。
#!lua name=library
redis.register_function {
function_name = 'add',
callback = function(keys, args) return redis.call('GET', keys[1]) + args[1] end,
flags = { 'no-writes' }
}
这是相同的示例,但格式可以粘贴到 redis-cli
中。
FUNCTION LOAD "#!lua name=library\nredis.register_function{function_name=\"add\", callback=function(keys, args) return redis.call('GET', keys[1])+args[1] end, flags={\"no-writes\"}}"
在运行以下示例之前,先在 redis 服务器 上加载上述 redis 函数。
import { createClient } from 'redis';
const client = createClient({
functions: {
library: {
add: {
NUMBER_OF_KEYS: 1,
transformArguments(key: string, toAdd: number): Array<string> {
return [key, toAdd.toString()];
},
transformReply(reply: number): number {
return reply;
}
}
}
}
});
await client.connect();
await client.set('key', '1');
await client.library.add('key', 2); // 3
Lua 脚本
以下是上述概念的端到端示例。
import { createClient, defineScript } from 'redis';
const client = createClient({
scripts: {
add: defineScript({
NUMBER_OF_KEYS: 1,
SCRIPT:
'return redis.call("GET", KEYS[1]) + ARGV[1];',
transformArguments(key: string, toAdd: number): Array<string> {
return [key, toAdd.toString()];
},
transformReply(reply: number): number {
return reply;
}
})
}
});
await client.connect();
await client.set('key', '1');
await client.add('key', 2); // 3
断开连接
有两个函数可以断开客户端与 Redis 服务器的连接。在大多数情况下,你应该使用 .quit()
以确保在关闭连接之前将待处理的命令发送到 Redis。
.QUIT()
/.quit()
通过向服务器发送 QUIT
命令,优雅地关闭客户端与 Redis 的连接。在退出之前,客户端会执行其队列中的任何剩余命令,并将从 Redis 收到每个命令的回复。
const [ping, get, quit] = await Promise.all([
client.ping(),
client.get('key'),
client.quit()
]); // ['PONG', null, 'OK']
try {
await client.get('key');
} catch (err) {
// ClosedClient 错误
}
.disconnect()
立即强制关闭客户端与 Redis 的连接。调用 disconnect
不会向 Redis 服务器发送进一步的待处理命令,也不会等待或解析未完成的响应。
await client.disconnect();
自动流水线
Node Redis 会自动将同一"tick"期间发出的请求组成流水线。
client.set('Tm9kZSBSZWRpcw==', 'users:1');
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==');
当然,如果你不处理你的 Promise,你肯定会得到未处理的 Promise 异常。要利用自动流水线并处理你的 Promise,请使用 Promise.all()
。
await Promise.all([
client.set('Tm9kZSBSZWRpcw==', 'users:1'),
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==')
]);
集群
在使用 Node Redis 连接到 Redis 集群时,请查看集群指南。
事件
Node Redis 客户端类是一个 Node.js EventEmitter,每当网络状态发生变化时它都会发出一个事件:
名称 | 何时 | 监听器参数 |
---|---|---|
connect | 正在初始化与服务器的连接 | 无参数 |
ready | 客户端准备就绪可以使用 | 无参数 |
end | 连接已关闭(通过 .quit() 或 .disconnect() ) | 无参数 |
error | 发生错误—通常是网络问题,如"Socket closed unexpectedly" | (error: Error) |
reconnecting | 客户端正在尝试重新连接到服务器 | 无参数 |
sharded-channel-moved | 参见这里 | 参见这里 |
:warning: 你必须监听
error
事件。如果客户端没有至少一个已注册的error
监听器,并且发生error
,那么该错误将被抛出,Node.js 进程将退出。有关更多详细信息,请参阅EventEmitter
文档。
客户端不会发出任何其他事件,除了上面列出的那些。
支持的 Redis 版本
Node Redis 支持以下版本的 Redis:
版本 | 支持 |
---|---|
7.0.z | :heavy_check_mark: |
6.2.z | :heavy_check_mark: |
6.0.z | :heavy_check_mark: |
5.0.z | :heavy_check_mark: |
< 5.0 | :x: |
Node Redis 应该可以与旧版本的 Redis 一起工作,但它没有经过全面测试,我们无法提供支持。
贡献
如果你想贡献,请查看贡献指南。
感谢所有已经为 Node Redis 做出贡献的人!
许可证
本仓库采用"MIT"许可证。参见LICENSE。