Redis 中文文档 Redis 中文文档
指南
redis.io (opens new window)
指南
redis.io (opens new window)
  • 关于
    • Redis 开源治理
    • Redis 发布周期
    • Redis 赞助商
  • 入门
  • 数据类型
  • Redis Stack
  • 命令
  • 手册
Build Status

A robust, performance-focused and full-featured Redis client for Node.js.

Supports Redis >= 2.6.12 and the latest version of Dragonfly. Completely compatible with Redis 7.x.

Features


ioredis is a robust, full-featured Redis client that is used in the world's biggest online commerce company Alibaba and many other awesome companies.

Full-featured. It supports Cluster, Sentinel, Streams, Pipelining, and of course Lua scripting, Redis Functions, Pub/Sub (with the support of binary messages).
High performance 🚀.
Delightful API 😄. It works with Node callbacks and Native promises.
Transformation of command arguments and replies.
Transparent key prefixing.
Abstraction for Lua scripting, allowing you to define custom commands.
Supports binary data.
Supports TLS 🔒.
Supports offline queue and ready checking.
Supports ES6 types, such as Map and Set.
Supports GEO commands 📍.
Supports Redis ACL.
Sophisticated error handling strategy.
Supports NAT mapping.
Supports autopipelining.

100% written in TypeScript and official declarations are provided:

TypeScript Screenshot

Versions


Version Branch Node.js Version Redis Version
:--- :--- :--- :---
5.x.x (latest) main >= 12 2.6.12 ~ latest
4.x.x v4 >= 6 2.6.12 ~ 7

Refer to CHANGELOG.md for features and bug fixes introduced in v5.

🚀Upgrading from v4 to v5

Links


API Documentation (Redis, Cluster )
Changelog
Migrating from node_redis

Sponsors


Upstash: Serverless Database for Redis


Upstash

Upstash is a Serverless Database with Redis/REST API and durable storage. It is the perfect database for your applications thanks to its per request pricing and low latency data.

Start for free in 30 seconds!

Medis: Redis GUI for macOS


Download on the App Store

Looking for a Redis GUI for macOS, Windows and Linux? Here's Medis !

Medis is an open-sourced, beautiful, easy-to-use Redis GUI management application.

Medis starts with all the basic features you need:

Keys viewing/editing
SSH Tunnel for connecting with remote servers
Terminal for executing custom commands
And other awesome features...

Medis 1 is open sourced on GitHub

Quick Start


Install


  1. ``` shell
  2. npm install ioredis
  3. ```

In a TypeScript project, you may want to add TypeScript declarations for Node.js:

  1. ``` shell
  2. npm install --save-dev @types/node
  3. ```

Basic Usage


  1. ``` js
  2. // Import ioredis.
  3. // You can also use `import { Redis } from "ioredis"`
  4. // if your project is a TypeScript project,
  5. // Note that `import Redis from "ioredis"` is still supported,
  6. // but will be deprecated in the next major version.
  7. const Redis = require("ioredis");

  8. // Create a Redis instance.
  9. // By default, it will connect to localhost:6379.
  10. // We are going to cover how to specify connection options soon.
  11. const redis = new Redis();

  12. redis.set("mykey", "value"); // Returns a promise which resolves to "OK" when the command succeeds.

  13. // ioredis supports the node.js callback style
  14. redis.get("mykey", (err, result) => {
  15.   if (err) {
  16.     console.error(err);
  17.   } else {
  18.     console.log(result); // Prints "value"
  19.   }
  20. });

  21. // Or ioredis returns a promise if the last argument isn't a function
  22. redis.get("mykey").then((result) => {
  23.   console.log(result); // Prints "value"
  24. });

  25. redis.zadd("sortedSet", 1, "one", 2, "dos", 4, "quatro", 3, "three");
  26. redis.zrange("sortedSet", 0, 2, "WITHSCORES").then((elements) => {
  27.   // ["one", "1", "dos", "2", "three", "3"] as if the command was `redis> ZRANGE sortedSet 0 2 WITHSCORES`
  28.   console.log(elements);
  29. });

  30. // All arguments are passed directly to the redis server,
  31. // so technically ioredis supports all Redis commands.
  32. // The format is: redis[SOME_REDIS_COMMAND_IN_LOWERCASE](ARGUMENTS_ARE_JOINED_INTO_COMMAND_STRING)
  33. // so the following statement is equivalent to the CLI: `redis> SET mykey hello EX 10`
  34. redis.set("mykey", "hello", "EX", 10);
  35. ```

See the examples/ folder for more examples. For example:

TTL
Strings
Hashes
Lists
Sets
Sorted Sets
Streams
Redis Modules e.g. RedisJSON

All Redis commands are supported. See the documentation for details.

Connect to Redis


When a new Redis instance is created, a connection to Redis will be created at the same time. You can specify which Redis to connect to by:

  1. ``` js
  2. new Redis(); // Connect to 127.0.0.1:6379
  3. new Redis(6380); // 127.0.0.1:6380
  4. new Redis(6379, "192.168.1.1"); // 192.168.1.1:6379
  5. new Redis("/tmp/redis.sock");
  6. new Redis({
  7.   port: 6379, // Redis port
  8.   host: "127.0.0.1", // Redis host
  9.   username: "default", // needs Redis >= 6
  10.   password: "my-top-secret",
  11.   db: 0, // Defaults to 0
  12. });
  13. ```

You can also specify connection options as a redis:// URL or rediss:// URL when using TLS encryption :

  1. ``` js
  2. // Connect to 127.0.0.1:6380, db 4, using password "authpassword":
  3. new Redis("redis://:authpassword@127.0.0.1:6380/4");

  4. // Username can also be passed via URI.
  5. new Redis("redis://username:authpassword@127.0.0.1:6380/4");
  6. ```

See API Documentation for all available options.

Pub/Sub


Redis provides several commands for developers to implement the Publish–subscribe pattern. There are two roles in this pattern: publisher and subscriber. Publishers are not programmed to send their messages to specific subscribers. Rather, published messages are characterized into channels, without knowledge of what (if any) subscribers there may be.

By leveraging Node.js's built-in events module, ioredis makes pub/sub very straightforward to use. Below is a simple example that consists of two files, one is publisher.js that publishes messages to a channel, the other is subscriber.js that listens for messages on specific channels.

  1. ``` js
  2. // publisher.js

  3. const Redis = require("ioredis");
  4. const redis = new Redis();

  5. setInterval(() => {
  6.   const message = { foo: Math.random() };
  7.   // Publish to my-channel-1 or my-channel-2 randomly.
  8.   const channel = `my-channel-${1 + Math.round(Math.random())}`;

  9.   // Message can be either a string or a buffer
  10.   redis.publish(channel, JSON.stringify(message));
  11.   console.log("Published %s to %s", message, channel);
  12. }, 1000);
  13. ```

  1. ``` js
  2. // subscriber.js

  3. const Redis = require("ioredis");
  4. const redis = new Redis();

  5. redis.subscribe("my-channel-1", "my-channel-2", (err, count) => {
  6.   if (err) {
  7.     // Just like other commands, subscribe() can fail for some reasons,
  8.     // ex network issues.
  9.     console.error("Failed to subscribe: %s", err.message);
  10.   } else {
  11.     // `count` represents the number of channels this client are currently subscribed to.
  12.     console.log(
  13.       `Subscribed successfully! This client is currently subscribed to ${count} channels.`
  14.     );
  15.   }
  16. });

  17. redis.on("message", (channel, message) => {
  18.   console.log(`Received ${message} from ${channel}`);
  19. });

  20. // There's also an event called 'messageBuffer', which is the same as 'message' except
  21. // it returns buffers instead of strings.
  22. // It's useful when the messages are binary data.
  23. redis.on("messageBuffer", (channel, message) => {
  24.   // Both `channel` and `message` are buffers.
  25.   console.log(channel, message);
  26. });
  27. ```

It's worth noticing that a connection (aka a Redis instance) can't play both roles at the same time. More specifically, when a client issues subscribe() or psubscribe(), it enters the "subscriber" mode. From that point, only commands that modify the subscription set are valid. Namely, they are: subscribe, psubscribe, unsubscribe, punsubscribe, ping, and quit. When the subscription set is empty (via unsubscribe /punsubscribe ), the connection is put back into the regular mode.

If you want to do pub/sub in the same file/process, you should create a separate connection:

  1. ``` js
  2. const Redis = require("ioredis");
  3. const sub = new Redis();
  4. const pub = new Redis();

  5. sub.subscribe(/* ... */); // From now, `sub` enters the subscriber mode.
  6. sub.on("message" /* ... */);

  7. setInterval(() => {
  8.   // `pub` can be used to publish messages, or send other regular commands (e.g. `hgetall`)
  9.   // because it's not in the subscriber mode.
  10.   pub.publish(/* ... */);
  11. }, 1000);
  12. ```

PSUBSCRIBE is also supported in a similar way when you want to subscribe all channels whose name matches a pattern:

  1. ``` js
  2. redis.psubscribe("pat?ern", (err, count) => {});

  3. // Event names are "pmessage"/"pmessageBuffer" instead of "message/messageBuffer".
  4. redis.on("pmessage", (pattern, channel, message) => {});
  5. redis.on("pmessageBuffer", (pattern, channel, message) => {});
  6. ```

Streams


Redis v5 introduces a new data type called streams. It doubles as a communication channel for building streaming architectures and as a log-like data structure for persisting data. With ioredis, the usage can be pretty straightforward. Say we have a producer publishes messages to a stream with redis.xadd("mystream", "*", "randomValue", Math.random()) (You may find the official documentation of Streams as a starter to understand the parameters used), to consume the messages, we'll have a consumer with the following code:

  1. ``` js
  2. const Redis = require("ioredis");
  3. const redis = new Redis();

  4. const processMessage = (message) => {
  5.   console.log("Id: %s. Data: %O", message[0], message[1]);
  6. };

  7. async function listenForMessage(lastId = "<%= main %>quot;) {
  8.   // `results` is an array, each element of which corresponds to a key.
  9.   // Because we only listen to one key (mystream) here, `results` only contains
  10.   // a single element. See more: https://redis.io/commands/xread#return-value
  11.   const results = await redis.xread("block", 0, "STREAMS", "mystream", lastId);
  12.   const [key, messages] = results[0]; // `key` equals to "mystream"

  13.   messages.forEach(processMessage);

  14.   // Pass the last id of the results to the next round.
  15.   await listenForMessage(messages[messages.length - 1][0]);
  16. }

  17. listenForMessage();
  18. ```

Handle Binary Data


Binary data support is out of the box. Pass buffers to send binary data:

  1. ``` js
  2. redis.set("foo", Buffer.from([0x62, 0x75, 0x66]));
  3. ```

Every command that returns a bulk string has a variant command with a Buffer suffix. The variant command returns a buffer instead of a UTF-8 string:

  1. ``` js
  2. const result = await redis.getBuffer("foo");
  3. // result is ``
  4. ```

It's worth noticing that you don't need the Buffer suffix variant in order to sendbinary data. That means in most case you should just use redis.set() instead of redis.setBuffer() unless you want to get the old value with the GET parameter:

  1. ``` js
  2. const result = await redis.setBuffer("foo", "new value", "GET");
  3. // result is `` as `GET` indicates returning the old value.
  4. ```

Pipelining


If you want to send a batch of commands (e.g. > 5), you can use pipelining to queue the commands in memory and then send them to Redis all at once. This way the performance improves by 50%~300% (See benchmark section ).

redis.pipeline() creates a Pipeline instance. You can call any Redis commands on it just like the Redis instance. The commands are queued in memory and flushed to Redis by calling the exec method:

  1. ``` js
  2. const pipeline = redis.pipeline();
  3. pipeline.set("foo", "bar");
  4. pipeline.del("cc");
  5. pipeline.exec((err, results) => {
  6.   // `err` is always null, and `results` is an array of responses
  7.   // corresponding to the sequence of queued commands.
  8.   // Each response follows the format `[err, result]`.
  9. });

  10. // You can even chain the commands:
  11. redis
  12.   .pipeline()
  13.   .set("foo", "bar")
  14.   .del("cc")
  15.   .exec((err, results) => {});

  16. // `exec` also returns a Promise:
  17. const promise = redis.pipeline().set("foo", "bar").get("foo").exec();
  18. promise.then((result) => {
  19.   // result === [[null, 'OK'], [null, 'bar']]
  20. });
  21. ```

Each chained command can also have a callback, which will be invoked when the command gets a reply:

  1. ``` js
  2. redis
  3.   .pipeline()
  4.   .set("foo", "bar")
  5.   .get("foo", (err, result) => {
  6.     // result === 'bar'
  7.   })
  8.   .exec((err, result) => {
  9.     // result[1][1] === 'bar'
  10.   });
  11. ```

In addition to adding commands to the pipeline queue individually, you can also pass an array of commands and arguments to the constructor:

  1. ``` js
  2. redis
  3.   .pipeline([
  4.     ["set", "foo", "bar"],
  5.     ["get", "foo"],
  6.   ])
  7.   .exec(() => {
  8.     /* ... */
  9.   });
  10. ```

#length property shows how many commands in the pipeline:

  1. ``` js
  2. const length = redis.pipeline().set("foo", "bar").get("foo").length;
  3. // length === 2
  4. ```

Transaction


Most of the time, the transaction commands multi & exec are used together with pipeline. Therefore, when multi is called, a Pipeline instance is created automatically by default, so you can use multi just like pipeline :

  1. ``` js
  2. redis
  3.   .multi()
  4.   .set("foo", "bar")
  5.   .get("foo")
  6.   .exec((err, results) => {
  7.     // results === [[null, 'OK'], [null, 'bar']]
  8.   });
  9. ```

If there's a syntax error in the transaction's command chain (e.g. wrong number of arguments, wrong command name, etc), then none of the commands would be executed, and an error is returned:

  1. ``` js
  2. redis
  3.   .multi()
  4.   .set("foo")
  5.   .set("foo", "new value")
  6.   .exec((err, results) => {
  7.     // err:
  8.     //  { [ReplyError: EXECABORT Transaction discarded because of previous errors.]
  9.     //    name: 'ReplyError',
  10.     //    message: 'EXECABORT Transaction discarded because of previous errors.',
  11.     //    command: { name: 'exec', args: [] },
  12.     //    previousErrors:
  13.     //     [ { [ReplyError: ERR wrong number of arguments for 'set' command]
  14.     //         name: 'ReplyError',
  15.     //         message: 'ERR wrong number of arguments for \'set\' command',
  16.     //         command: [Object] } ] }
  17.   });
  18. ```

In terms of the interface, multi differs from pipeline in that when specifying a callback to each chained command, the queueing state is passed to the callback instead of the result of the command:

  1. ``` js
  2. redis
  3.   .multi()
  4.   .set("foo", "bar", (err, result) => {
  5.     // result === 'QUEUED'
  6.   })
  7.   .exec(/* ... */);
  8. ```

If you want to use transaction without pipeline, pass { pipeline: false } to multi, and every command will be sent to Redis immediately without waiting for an exec invocation:

  1. ``` js
  2. redis.multi({ pipeline: false });
  3. redis.set("foo", "bar");
  4. redis.get("foo");
  5. redis.exec((err, result) => {
  6.   // result === [[null, 'OK'], [null, 'bar']]
  7. });
  8. ```

The constructor of multi also accepts a batch of commands:

  1. ``` js
  2. redis
  3.   .multi([
  4.     ["set", "foo", "bar"],
  5.     ["get", "foo"],
  6.   ])
  7.   .exec(() => {
  8.     /* ... */
  9.   });
  10. ```

Inline transactions are supported by pipeline, which means you can group a subset of commands in the pipeline into a transaction:

  1. ``` js
  2. redis
  3.   .pipeline()
Last Updated: 2023-09-03 19:17:54