Redis 适配器
工作原理
¥How it works
Redis 适配器依赖于 Redis 发布/订阅机制。
¥The Redis adapter relies on the Redis Pub/Sub mechanism.
发送到多个客户端(例如 io.to("room1").emit()
或 socket.broadcast.emit()
)的每个数据包是:
¥Every packet that is sent to multiple clients (e.g. io.to("room1").emit()
or socket.broadcast.emit()
) is:
发送到连接到当前服务器的所有匹配客户端
¥sent to all matching clients connected to the current server
在 Redis 通道中发布,并由集群中的其他 Socket.IO 服务器接收
¥published in a Redis channel, and received by the other Socket.IO servers of the cluster
该适配器的源代码可以找到 此处。
¥The source code of this adapter can be found here.
支持的功能
¥Supported features
特性 | socket.io 版本 | 支持 |
---|---|---|
套接字管理 | 4.0.0 | :白色复选标记:是(自版本 6.1.0 起) |
服务器间通信 | 4.1.0 | :白色复选标记:是(自版本 7.0.0 起) |
广播并致谢 | 4.5.0 | :白色复选标记:是(自版本 7.2.0 起) |
连接状态恢复 | 4.6.0 | :X:不 |
安装
¥Installation
npm install @socket.io/redis-adapter
兼容性表
¥Compatibility table
Redis 适配器版本 | Socket.IO 服务器版本 |
---|---|
4.x | 1.x |
5.x | 2.x |
6.0.x | 3.x |
6.1.x | 4.x |
7.x 及以上 | 4.3.1 及以上 |
用法
¥Usage
使用 redis
包
¥With the redis
package
import { createClient } from "redis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const pubClient = createClient({ url: "redis://localhost:6379" });
const subClient = pubClient.duplicate();
await Promise.all([
pubClient.connect(),
subClient.connect()
]);
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
使用 redis
包和 Redis 集群
¥With the redis
package and a Redis cluster
import { createCluster } from "redis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const pubClient = createCluster({
rootNodes: [
{
url: "redis://localhost:7000",
},
{
url: "redis://localhost:7001",
},
{
url: "redis://localhost:7002",
},
],
});
const subClient = pubClient.duplicate();
await Promise.all([
pubClient.connect(),
subClient.connect()
]);
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
使用 ioredis
包
¥With the ioredis
package
import { Redis } from "ioredis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const pubClient = new Redis();
const subClient = pubClient.duplicate();
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
使用 ioredis
包和 Redis 集群
¥With the ioredis
package and a Redis cluster
import { Cluster } from "ioredis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const pubClient = new Cluster([
{
host: "localhost",
port: 7000,
},
{
host: "localhost",
port: 7001,
},
{
host: "localhost",
port: 7002,
},
]);
const subClient = pubClient.duplicate();
const io = new Server({
adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
使用 Redis 共享 Pub/Sub
¥With Redis sharded Pub/Sub
Redis 7.0 中引入了分片 Pub/Sub,以帮助扩展集群模式下 Pub/Sub 的使用。
¥Sharded Pub/Sub was introduced in Redis 7.0 in order to help scaling the usage of Pub/Sub in cluster mode.
参考:https://redis.io/docs/interact/pubsub/#sharded-pubsub
¥Reference: https://redis.io/docs/interact/pubsub/#sharded-pubsub
可以使用 createShardedAdapter()
方法创建专用适配器:
¥A dedicated adapter can be created with the createShardedAdapter()
method:
import { Server } from "socket.io";
import { createClient } from "redis";
import { createShardedAdapter } from "@socket.io/redis-adapter";
const pubClient = createClient({ host: "localhost", port: 6379 });
const subClient = pubClient.duplicate();
await Promise.all([
pubClient.connect(),
subClient.connect()
]);
const io = new Server({
adapter: createShardedAdapter(pubClient, subClient)
});
io.listen(3000);
最低要求:
¥Minimum requirements:
Redis 7.0
选项
¥Options
默认适配器
¥Default adapter
名称 | 描述 | 默认值 |
---|---|---|
key | Redis Pub/Sub 通道的前缀。 | socket.io |
requestsTimeout | 超时后,适配器将停止等待请求响应。 | 5_000 |
publishOnSpecificResponseChannel | 是否将响应发布到特定于请求节点的通道。 | false |
parser | 用于对发送到 Redis 的消息进行编码和解码的解析器。 | - |
将 publishOnSpecificResponseChannel
选项设置为 true
会更有效,因为响应(例如,调用 fetchSockets()
或 serverSideEmit()
时)仅发送到请求服务器,而不是发送到所有服务器。
¥Setting the publishOnSpecificResponseChannel
option to true
is more efficient since the responses (for example when calling fetchSockets()
or serverSideEmit()
) are only sent to the requesting server, and not to all the servers.
但是,为了向后兼容,它目前默认为 false
。
¥However, it currently defaults to false
for backward-compatibility.
共享适配器
¥Sharded adapter
名称 | 描述 | 默认值 |
---|---|---|
channelPrefix | Redis Pub/Sub 通道的前缀。 | socket.io |
subscriptionMode | 订阅模式会影响适配器使用的 Redis Pub/Sub 通道的数量。 | dynamic |
常见问题
¥Common questions
Redis 中是否存储有数据?
¥Is there any data stored in Redis?
不,Redis 适配器使用 发布/订阅机制 在 Socket.IO 服务器之间转发数据包,因此 Redis 中没有存储密钥。
¥No, the Redis adapter uses the Pub/Sub mechanism to forward the packets between the Socket.IO servers, so there are no keys stored in Redis.
使用 Redis 适配器时是否仍需要启用粘性会话?
¥Do I still need to enable sticky sessions when using the Redis adapter?
是的。如果不这样做,将导致 HTTP 400 响应(你正在访问不知道 Socket.IO 会话的服务器)。
¥Yes. Failing to do so will result in HTTP 400 responses (you are reaching a server that is not aware of the Socket.IO session).
更多信息可参见 此处。
¥More information can be found here.
当 Redis 服务器宕机时会发生什么?
¥What happens when the Redis server is down?
如果与 Redis 服务器的连接被切断,数据包只会发送到与当前服务器连接的客户端。
¥In case the connection to the Redis server is severed, the packets will only be sent to the clients that are connected to the current server.
从 socket.io-redis
迁移
¥Migrating from socket.io-redis
该包在 v7 中从 socket.io-redis
重命名为 @socket.io/redis-adapter
,以匹配 Redis 触发器的名称 (@socket.io/redis-emitter
)。
¥The package was renamed from socket.io-redis
to @socket.io/redis-adapter
in v7, in order to match the name of the Redis emitter (@socket.io/redis-emitter
).
要迁移到新包,你需要确保提供自己的 Redis 客户端,因为该包将不再代表用户创建 Redis 客户端。
¥To migrate to the new package, you'll need to make sure to provide your own Redis clients, as the package will no longer create Redis clients on behalf of the user.
前:
¥Before:
const redisAdapter = require("socket.io-redis");
io.adapter(redisAdapter({ host: "localhost", port: 6379 }));
后:
¥After:
const { createClient } = require("redis");
const { createAdapter } = require("@socket.io/redis-adapter");
const pubClient = createClient({ url: "redis://localhost:6379" });
const subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));
Socket.IO 服务器之间的通信协议尚未更新,因此你可以同时拥有一些带有 socket.io-redis
的服务器和一些带有 @socket.io/redis-adapter
的服务器。
¥The communication protocol between the Socket.IO servers has not been updated, so you can have some servers with socket.io-redis
and some others with @socket.io/redis-adapter
at the same time.
最新版本
¥Latest releases
版本 | 发布日期 | 发行说明 | 差异 |
---|---|---|---|
8.3.0 | 2024 年 3 月 | link | 8.2.1...8.3.0 |
8.2.1 | 2023 年 5 月 | link | 8.2.0...8.2.1 |
8.2.0 | 2023 年 5 月 | link | 8.1.0...8.2.0 |
8.1.0 | 2023 年 2 月 | link | 8.0.0...8.1.0 |
8.0.0 | 2022 年 12 月 | link | 7.2.0...8.0.0 |
7.2.0 | 2022 年 5 月 | link | 7.1.0...7.2.0 |
触发器
¥Emitter
Redis 触发器允许从另一个 Node.js 进程向连接的客户端发送数据包:
¥The Redis emitter allows sending packets to the connected clients from another Node.js process:
该触发器还有多种语言版本:
¥This emitter is also available in several languages:
JavaScript:https://github.com/socketio/socket.io-redis-emitter
Golang:https://github.com/yosuke-furukawa/socket.io-go-emitter
安装
¥Installation
npm install @socket.io/redis-emitter redis
用法
¥Usage
import { Emitter } from "@socket.io/redis-emitter";
import { createClient } from "redis";
const redisClient = createClient({ url: "redis://localhost:6379" });
redisClient.connect().then(() => {
const emitter = new Emitter(redisClient);
setInterval(() => {
emitter.emit("time", new Date);
}, 5000);
});
注意:使用 redis@3
,不需要在 Redis 客户端上调用 connect()
:
¥Note: with redis@3
, calling connect()
on the Redis client is not needed:
import { Emitter } from "@socket.io/redis-emitter";
import { createClient } from "redis";
const redisClient = createClient({ url: "redis://localhost:6379" });
const emitter = new Emitter(redisClient);
setInterval(() => {
emitter.emit("time", new Date);
}, 5000);
请参阅备忘单 此处。
¥Please refer to the cheatsheet here.
从 socket.io-emitter
迁移
¥Migrating from socket.io-emitter
该包在 v4 年从 socket.io-emitter
更名为 @socket.io/redis-emitter
,以便更好地体现与 Redis 的关系。
¥The package was renamed from socket.io-emitter
to @socket.io/redis-emitter
in v4, in order to better reflect the relationship with Redis.
要迁移到新包,你需要确保提供自己的 Redis 客户端,因为该包将不再代表用户创建 Redis 客户端。
¥To migrate to the new package, you'll need to make sure to provide your own Redis clients, as the package will no longer create Redis clients on behalf of the user.
前:
¥Before:
const io = require("socket.io-emitter")({ host: "127.0.0.1", port: 6379 });
后:
¥After:
const { Emitter } = require("@socket.io/redis-emitter");
const { createClient } = require("redis");
const redisClient = createClient();
const io = new Emitter(redisClient);
最新版本
¥Latest releases
版本 | 发布日期 | 发行说明 | 差异 |
---|---|---|---|
5.1.0 | 2023 年 1 月 | link | 5.0.0...5.1.0 |
5.0.0 | 2022 年 9 月 | link | 4.1.1...5.0.0 |
4.1.1 | 2022 年 1 月 | link | 4.1.0...4.1.1 |
4.1.0 | 2021 年 5 月 | link | 4.0.0...4.1.0 |
4.0.0 | 2021 年 3 月 | link | 3.2.0...4.0.0 |