Redisアダプター
仕組み
Redisアダプターは、RedisのPub/Subメカニズムに依存しています。
複数のクライアントに送信されるすべてのパケット (例: io.to("room1").emit() または socket.broadcast.emit()) は
- 現在のサーバーに接続されているすべての一致するクライアントに送信されます
- Redisチャネルにパブリッシュされ、クラスターの他のSocket.IOサーバーによって受信されます


このアダプターのソースコードはこちらにあります。
対応機能
| 機能 | socket.ioバージョン | 対応状況 | 
|---|---|---|
| ソケット管理 | 4.0.0 | ✅ 対応 (バージョン 6.1.0以降) | 
| サーバー間通信 | 4.1.0 | ✅ 対応 (バージョン 7.0.0以降) | 
| 確認応答付きブロードキャスト | 4.5.0 | ✅ 対応 (バージョン 7.2.0以降) | 
| 接続状態の復旧 | 4.6.0 | ❌ 未対応 | 
インストール
npm install @socket.io/redis-adapter
互換性一覧
| 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以上 | 
使用方法
redisパッケージを使用する場合
redisパッケージは、再接続後にRedisサブスクリプションの復元に問題があるようです
代わりにioredisパッケージを使用することをお勧めします。
import { createClient } from "redis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const pubClient = createClient({ url: "redis://: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クラスタを使用する場合
import { createCluster } from "redis";
import { Server } from "socket.io";
import { createAdapter } from "@socket.io/redis-adapter";
const pubClient = createCluster({
  rootNodes: [
    {
      url: "redis://:7000",
    },
    {
      url: "redis://:7001",
    },
    {
      url: "redis://:7002",
    },
  ],
});
const subClient = pubClient.duplicate();
await Promise.all([
  pubClient.connect(),
  subClient.connect()
]);
const io = new Server({
  adapter: createAdapter(pubClient, subClient)
});
io.listen(3000);
ioredisパッケージを使用する場合
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クラスタを使用する場合
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を使用する場合
シャーデッドPub/Subは、Redis 7.0で導入され、クラスターモードでのPub/Subの使用をスケーリングするのに役立ちます。
参考資料: https://redis.io/docs/interact/pubsub/#sharded-pubsub
専用の adapter は、`createShardedAdapter()` メソッドを使用して作成できます。
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);
最低要件
- Redis 7.0
- redis@4.6.0
現在、`ioredis` パッケージと Redis クラスタを使用してシャーデッドアダプタを使用することはできません(参考資料)。
オプション
デフォルトアダプター
| 名前 | 説明 | デフォルト値 | 
|---|---|---|
| key | Redis Pub/Subチャネルのプレフィックス。 | socket.io | 
| requestsTimeout | このタイムアウト後、アダプターはリクエストへの応答の待機を停止します。 | 5_000 | 
| publishOnSpecificResponseChannel | リクエスト元のノードに固有のチャネルに応答をパブリッシュするかどうか。 | false | 
| parser | Redisに送信されるメッセージのエンコードとデコードに使用するパーサー。 | - | 
publishOnSpecificResponseChannelオプションをtrueに設定すると、応答(たとえば、fetchSockets()またはserverSideEmit()を呼び出す場合)がすべてではなく、リクエスト元のサーバーのみに送信されるため、より効率的です。サーバー。
ただし、現在、下位互換性のためにデフォルトでfalseになっています。
シャーデッドアダプター
| 名前 | 説明 | デフォルト値 | 
|---|---|---|
| channelPrefix | Redis Pub/Subチャネルのプレフィックス。 | socket.io | 
| subscriptionMode | サブスクリプションモードは、アダプターが使用するRedis Pub/Subチャネルの数に影響します。 | dynamic | 
よくある質問
Redisにデータは保存されますか?
いいえ、RedisアダプターはPub/Subメカニズムを使用してSocket.IOサーバー間でパケットを転送するため、Redisにキーは保存されません。
Redisアダプターを使用する場合でも、スティッキーセッションを有効にする必要がありますか?
はい。有効にしないと、HTTP 400応答が返されます(Socket.IOセッションを認識していないサーバーにアクセスしています)。
詳細については、こちらをご覧ください。
Redisサーバーがダウンした場合はどうなりますか?
Redisサーバーへの接続が切断された場合、パケットは現在のサーバーに接続されているクライアントにのみ送信されます。
socket.io-redisからの移行
Redisエミッター(@socket.io/redis-emitter)の名前と一致させるために、パッケージの名前がv7でsocket.io-redisから@socket.io/redis-adapterに変更されました。
新しいパッケージに移行するには、パッケージはユーザーに代わってRedisクライアントを作成しなくなるため、独自のRedisクライアントを提供する必要があることを確認してください.
変更前
const redisAdapter = require("socket.io-redis");
io.adapter(redisAdapter({ host: "localhost", port: 6379 }));
変更後
const { createClient } = require("redis");
const { createAdapter } = require("@socket.io/redis-adapter");
const pubClient = createClient({ url: "redis://:6379" });
const subClient = pubClient.duplicate();
io.adapter(createAdapter(pubClient, subClient));
Socket.IOサーバー間の通信プロトコルは更新されていないため、socket.io-redisを使用するサーバーと@socket.io/redis-adapterを使用するサーバーを同時に使用できます。
最新リリース
| バージョン | リリース日 | リリースノート | 差分 | 
|---|---|---|---|
| 8.3.0 | 2024年3月 | リンク | 8.2.1...8.3.0 | 
| 8.2.1 | 2023年5月 | リンク | 8.2.0...8.2.1 | 
| 8.2.0 | 2023年5月 | リンク | 8.1.0...8.2.0 | 
| 8.1.0 | 2023年2月 | リンク | 8.0.0...8.1.0 | 
| 8.0.0 | 2022年12月 | リンク | 7.2.0...8.0.0 | 
| 7.2.0 | 2022年5月 | リンク | 7.1.0...7.2.0 | 
エミッター
Redisエミッターを使用すると、別のNode.jsプロセスから接続されているクライアントにパケットを送信できます


このエミッターは、いくつかの言語でも利用できます
- Javascript: https://github.com/socketio/socket.io-redis-emitter
- Java: https://github.com/sunsus/socket.io-java-emitter
- Python: https://pypi.org/project/socket.io-emitter/
- PHP: https://github.com/rase-/socket.io-php-emitter
- Golang: https://github.com/yosuke-furukawa/socket.io-go-emitter
- Perl: https://metacpan.org/pod/SocketIO::Emitter
- Rust: https://github.com/epli2/socketio-rust-emitter
インストール
npm install @socket.io/redis-emitter redis
使用方法
import { Emitter } from "@socket.io/redis-emitter";
import { createClient } from "redis";
const redisClient = createClient({ url: "redis://:6379" });
redisClient.connect().then(() => {
  const emitter = new Emitter(redisClient);
  setInterval(() => {
    emitter.emit("time", new Date);
  }, 5000);
});
注: redis@3を使用する場合、Redisクライアントでconnect()を呼び出す必要はありません
import { Emitter } from "@socket.io/redis-emitter";
import { createClient } from "redis";
const redisClient = createClient({ url: "redis://:6379" });
const emitter = new Emitter(redisClient);
setInterval(() => {
  emitter.emit("time", new Date);
}, 5000);
チートシートはこちらを参照してください。
socket.io-emitterからの移行
Redisとの関係をより明確に反映するために、パッケージの名前がv4でsocket.io-emitterから@socket.io/redis-emitterに変更されました。
新しいパッケージに移行するには、パッケージはユーザーに代わってRedisクライアントを作成しなくなるため、独自のRedisクライアントを提供する必要があることを確認してください.
変更前
const io = require("socket.io-emitter")({ host: "127.0.0.1", port: 6379 });
変更後
const { Emitter } = require("@socket.io/redis-emitter");
const { createClient } = require("redis");
const redisClient = createClient();
const io = new Emitter(redisClient);
最新リリース
| バージョン | リリース日 | リリースノート | 差分 | 
|---|---|---|---|
| 5.1.0 | 2023年1月 | リンク | 5.0.0...5.1.0 | 
| 5.0.0 | 2022年9月 | リンク | 4.1.1...5.0.0 | 
| 4.1.1 | 2022年1月 | リンク | 4.1.0...4.1.1 | 
| 4.1.0 | 2021年5月 | リンク | 4.0.0...4.1.0 | 
| 4.0.0 | 2021年3月 | リンク | 3.2.0...4.0.0 |