Redis 中文网
node-redis 是 Node.js 的现代、高性能 Redis 客户端。
¥node-redis is a modern, high performance Redis client for Node.js.
包
¥Packages
名称 | 描述 |
---|---|
redis | |
@redis/client | |
@redis/bloom | Redis Bloom 命令 |
@redis/graph | Redis Graph 命令 |
@redis/json | Redis JSON 命令 |
@redis/search | RediSearch 命令 |
@redis/time-series | Redis 时间序列 命令 |
⚠️在版本 4.1.0 中,我们将子包从
@node-redis
移到了@redis
。如果你只是使用npm install redis
,则无需执行任何操作 - 它会自动升级。如果你直接使用子包,则需要指向新的范围(例如@redis/client
而不是@node-redis/client
)。¥⚠️ In version 4.1.0 we moved our subpackages from
@node-redis
to@redis
. If you're just usingnpm install redis
, you don't need to do anything—it'll upgrade automatically. If you're using the subpackages directly, you'll need to point to the new scope (e.g.@redis/client
instead of@node-redis/client
).
安装
¥Installation
通过 docker 启动 redis:
¥Start a redis via docker:
docker run -p 6379:6379 -it redis/redis-stack-server:latest
要安装 node-redis,只需:
¥To install node-redis, simply:
npm install redis
⚠️新界面简洁酷炫,但如果你有现有的代码库,则需要阅读 迁移指南。
¥⚠️ The new interface is clean and cool, but if you have an existing codebase, you'll want to read the migration guide.
正在寻找处理对象映射的高级库?参见 redis-om-node!
¥Looking for a high-level library to handle object mapping? See redis-om-node!
用法
¥Usage
基本示例
¥Basic Example
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');
await client.disconnect();
上面的代码连接到端口 6379 上的本地主机。要连接到不同的主机或端口,请使用格式为 redis[s]://[[username][:password]@][host][:port][/db-number]
的连接字符串:
¥The above code connects to localhost on port 6379. To connect to a different host or port, use a connection string in the format redis[s]://[[username][:password]@][host][:port][/db-number]
:
createClient({
url: 'redis://alice:foobared@awesome.redis.server:6380'
});
你还可以使用离散参数、UNIX 套接字甚至 TLS 进行连接。详细信息可以在 客户端配置指南 中找到。
¥You can also use discrete parameters, UNIX sockets, and even TLS to connect. Details can be found in the client configuration guide.
要检查客户端是否已连接并准备好发送命令,请使用返回布尔值的 client.isReady
。client.isOpen
也可用。当客户端的底层套接字打开时,这将返回 true
,当它未打开时(例如,当客户端仍在连接或在网络错误后重新连接时),这将返回 false
。
¥To check if the the client is connected and ready to send commands, use client.isReady
which returns a boolean. client.isOpen
is also available. This returns true
when the client's underlying socket is open, and false
when it isn't (for example when the client is still connecting or reconnecting after a network error).
Redis 命令
¥Redis Commands
内置支持所有 开箱即用的 Redis 命令。它们使用原始 Redis 命令名称(HSET
、HGETALL
等)和更友好的驼峰式版本(hSet
、hGetAll
等)公开:
¥There is built-in support for all of the out-of-the-box Redis commands. They are exposed using the raw Redis command names (HSET
, HGETALL
, etc.) and a friendlier camel-cased version (hSet
, hGetAll
, etc.):
// 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 对象指定命令的修饰符:
¥Modifiers to commands are specified using a JavaScript object:
await client.set('key', 'value', {
EX: 10,
NX: true
});
回复将转换为有用的数据结构:
¥Replies will be transformed into useful data structures:
await client.hGetAll('key'); // { field1: 'value1', field2: 'value2' }
await client.hVals('key'); // ['value1', 'value2']
Buffer
也受支持:
¥Buffer
s are supported as well:
await client.hSet('key', 'field', Buffer.from('value')); // 'OK'
await client.hGetAll(
commandOptions({ returnBuffers: true }),
'key'
); // { field: <Buffer 76 61 6c 75 65> }
不支持的 Redis 命令
¥Unsupported Redis Commands
如果你想运行 Node Redis 尚不知道的命令和/或参数,请使用 .sendCommand()
:
¥If you want to run commands and/or use arguments that Node Redis doesn't know about (yet!) use .sendCommand()
:
await client.sendCommand(['SET', 'key', 'value', 'NX']); // 'OK'
await client.sendCommand(['HGETALL', 'key']); // ['key1', 'field1', 'key2', 'field2']
事务 (Multi/Exec)
¥Transactions (Multi/Exec)
通过调用 .multi()
启动 transaction,然后链接你的命令。完成后,调用 .exec()
,你将得到一个包含结果的数组:
¥Start a transaction by calling .multi()
, then chaining your commands. When you're done, call .exec()
and you'll get an array back with your results:
await client.set('another-key', 'another-value');
const [setKeyReply, otherKeyValue] = await client
.multi()
.set('key', 'value')
.get('another-key')
.exec(); // ['OK', 'another-value']
你还可以通过调用 .watch()
来 watch 键。如果任何监视的键发生变化,你的事务将中止。
¥You can also watch keys by calling .watch()
. Your transaction will abort if any of the watched keys change.
要深入了解事务,请查看 隔离执行指南。
¥To dig deeper into transactions, check out the Isolated Execution Guide.
阻塞命令
¥Blocking Commands
通过指定 isolated
选项,可以在新连接上运行任何命令。当命令的 Promise
完成时,新创建的连接将关闭。
¥Any command can be run on a new connection by specifying the isolated
option. The newly created connection is closed when the command's Promise
is fulfilled.
此模式特别适用于阻止命令 - 例如 BLPOP
和 BLMOVE
:
¥This pattern works especially well for blocking commands—such as BLPOP
and BLMOVE
:
import { commandOptions } from 'redis';
const blPopPromise = client.blPop(
commandOptions({ isolated: true }),
'key',
0
);
await client.lPush('key', ['1', '2']);
await blPopPromise; // '2'
要了解有关隔离执行的更多信息,请查看 guide。
¥To learn more about isolated execution, check out the guide.
发布/订阅
¥Pub/Sub
参见 发布/订阅概述。
¥See the Pub/Sub overview.
扫描迭代器
¥Scan Iterator
¥SCAN
results can be looped over using async iterators:
for await (const key of client.scanIterator()) {
// use the key!
await client.get(key);
}
这也适用于 HSCAN
、SSCAN
和 ZSCAN
:
¥This works with HSCAN
, SSCAN
, and ZSCAN
too:
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')) {}
你可以通过提供配置对象来覆盖默认选项:
¥You can override the default options by providing a configuration object:
client.scanIterator({
TYPE: 'string', // `SCAN` only
MATCH: 'patter*',
COUNT: 100
});
可编程性
Redis 提供了一个编程接口,允许在 redis 服务器上执行代码。
¥Redis provides a programming interface allowing code execution on the redis server.
函数
以下示例检索 redis 中的键,返回键的值,并增加一个整数。例如,如果你的键 foo 的值为 17,并且我们运行 add('foo', 25)
,它将返回生命、宇宙和万物的答案。
¥The following example retrieves a key in redis, returning the value of the key, incremented by an integer. For example, if your key foo has the value 17 and we run add('foo', 25)
, it returns the answer to Life, the Universe and Everything.
#!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
中。
¥Here is the same example, but in a format that can be pasted into the 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 函数。
¥Load the prior redis function on the redis server before running the example below.
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 脚本
以下是先前概念的端到端示例。
¥The following is an end-to-end example of the prior concept.
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
断开连接
¥Disconnecting
有两个函数可以断开客户端与 Redis 服务器的连接。在大多数情况下,你应该使用 .quit()
来确保在关闭连接之前将待处理的命令发送到 Redis。
¥There are two functions that disconnect a client from the Redis server. In most scenarios you should use .quit()
to ensure that pending commands are sent to Redis before closing a connection.
.QUIT()
/.quit()
通过向服务器发送 QUIT
命令,优雅地关闭客户端与 Redis 的连接。在退出之前,客户端将执行其队列中剩余的所有命令,并将从 Redis 接收每个命令的回复。
¥Gracefully close a client's connection to Redis, by sending the QUIT
command to the server. Before quitting, the client executes any remaining commands in its queue, and will receive replies from Redis for each of them.
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 Error
}
.disconnect()
立即强制关闭客户端与 Redis 的连接。调用 disconnect
不会向 Redis 服务器发送其他待处理命令,也不会等待或解析未完成的响应。
¥Forcibly close a client's connection to Redis immediately. Calling disconnect
will not send further pending commands to the Redis server, or wait for or parse outstanding responses.
await client.disconnect();
自动流水线
¥Auto-Pipelining
Node Redis 将自动对在同一 "tick" 期间发出的请求进行管道处理。
¥Node Redis will automatically pipeline requests that are made during the same "tick".
client.set('Tm9kZSBSZWRpcw==', 'users:1');
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==');
当然,如果你不对 Promises 执行任何操作,你肯定会得到 未处理的 Promise 异常。要利用自动流水线并处理你的 Promises,请使用 Promise.all()
。
¥Of course, if you don't do something with your Promises you're certain to get unhandled Promise exceptions. To take advantage of auto-pipelining and handle your Promises, use Promise.all()
.
await Promise.all([
client.set('Tm9kZSBSZWRpcw==', 'users:1'),
client.sAdd('users:1:tokens', 'Tm9kZSBSZWRpcw==')
]);
集群
¥Clustering
使用 Node Redis 连接到 Redis 集群时,请查看 集群指南。
¥Check out the Clustering Guide when using Node Redis to connect to a Redis Cluster.
事件
¥Events
Node Redis 客户端类是一个 Nodejs EventEmitter,每次网络状态发生变化时它都会发出一个事件:
¥The Node Redis client class is an Nodejs EventEmitter and it emits an event each time the network status changes:
名称 | 时间 | 监听器参数 |
---|---|---|
connect | 启动与服务器的连接 | 无参数 |
ready | 客户端已准备好使用 | 无参数 |
end | 连接已关闭(通过 .quit() 或 .disconnect() ) | 无参数 |
error | 发生错误 — 通常是网络问题,例如 "套接字意外关闭" | (error: Error) |
reconnecting | 客户端正在尝试重新连接到服务器 | 无参数 |
sharded-channel-moved | 参见 此处 | 参见 此处 |
⚠️你必须监听
error
事件。如果客户端没有注册至少一个error
监听器并且发生error
,则会抛出该错误并且 Node.js 进程将退出。有关更多详细信息,请参阅EventEmitter
文档。¥⚠️ You MUST listen to
error
events. If a client doesn't have at least oneerror
listener registered and anerror
occurs, that error will be thrown and the Node.js process will exit. See theEventEmitter
docs for more details.
客户端不会发出上面列出的 任何其他事件。
¥The client will not emit any other events beyond those listed above.
支持的 Redis 版本
¥Supported Redis versions
以下版本的 Redis 支持 Node Redis:
¥Node Redis is supported with the following versions of 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 | ❌ |
Node Redis 应该可以与旧版本的 Redis 一起使用,但它尚未经过全面测试,我们无法提供支持。
¥Node Redis should work with older versions of Redis, but it is not fully tested and we cannot offer support.
贡献
¥Contributing
如果你想做出贡献,请查看 贡献指南。
¥If you'd like to contribute, check out the contributing guide.
感谢所有为 Node Redis 做出贡献的人!
¥Thank you to all the people who already contributed to Node Redis!
许可证
¥License
此存储库根据 "MIT" 许可证获得许可。参见 LICENSE。
¥This repository is licensed under the "MIT" license. See LICENSE.