ioredis の使い方 — Node.js向け高機能Redisクライアント完全ガイド
一言でいうと
ioredis は、Node.js 向けの高性能かつフル機能の Redis クライアントです。Cluster、Sentinel、Pipelining、Pub/Sub、Lua スクリプティングなど Redis の主要機能をすべてサポートし、TypeScript で書かれた堅牢なライブラリです。
どんな時に使う?
- Webアプリケーションのキャッシュ層 — セッション管理やAPIレスポンスのキャッシュなど、高速なデータアクセスが必要な場面
- リアルタイム通信 — Pub/Sub を活用したチャット、通知、イベント配信システムの構築
- 大規模分散システム — Redis Cluster や Sentinel を使った高可用性・スケーラブルなアーキテクチャの実装
- ジョブキュー・レートリミッター — BullMQ などのジョブキューライブラリの内部クライアントとして(BullMQ は ioredis に依存しています)
注意: README にも記載がありますが、新規プロジェクトでは公式が node-redis を推奨しています。ioredis は安定版としてメンテナンスが継続されていますが、Redis 8 の新機能(Search、JSON、Time-Series 等)への対応は node-redis が先行しています。既存プロジェクトや Cluster/Sentinel を多用するケースでは ioredis は依然として有力な選択肢です。
インストール
# npm
npm install ioredis
# yarn
yarn add ioredis
# pnpm
pnpm add ioredis
TypeScript プロジェクトでは Node.js の型定義も追加しておきましょう(ioredis 自体は型定義を同梱しています)。
npm install --save-dev @types/node
基本的な使い方
最もよく使うパターンとして、接続・SET/GET・切断の流れを示します。
import Redis from "ioredis";
// デフォルトで localhost:6379 に接続
const redis = new Redis();
// 接続オプションを指定する場合
// const redis = new Redis({
// host: "127.0.0.1",
// port: 6379,
// password: "my-top-secret",
// db: 0,
// });
async function main() {
// SET: キーに値をセット(TTL 60秒)
await redis.set("user:1:name", "Taro", "EX", 60);
// GET: 値を取得
const name = await redis.get("user:1:name");
console.log(name); // "Taro"
// DEL: キーを削除
await redis.del("user:1:name");
// 接続を閉じる
await redis.quit();
}
main().catch(console.error);
URL 形式での接続も可能です。
const redis = new Redis("redis://:authpassword@127.0.0.1:6380/4");
// TLS 接続の場合
const redisTls = new Redis("rediss://username:password@my-redis.example.com:6380");
よく使うAPI — ioredis の使い方を実践的に解説
1. ハッシュ操作(hset / hgetall)
ユーザー情報のようなオブジェクトを格納するのに最適です。
import Redis from "ioredis";
const redis = new Redis();
async function hashExample() {
// 複数フィールドを一括セット
await redis.hset("user:100", {
name: "Taro Yamada",
email: "taro@example.com",
age: "30",
});
// 単一フィールドの取得
const name = await redis.hget("user:100", "name");
console.log(name); // "Taro Yamada"
// 全フィールドを取得(Record<string, string> として返る)
const user = await redis.hgetall("user:100");
console.log(user);
// { name: "Taro Yamada", email: "taro@example.com", age: "30" }
await redis.quit();
}
hashExample();
2. Pub/Sub(publish / subscribe)
リアルタイムなメッセージ配信に使います。Subscriber 用と Publisher 用で別々の Redis インスタンスが必要な点に注意してください。
import Redis from "ioredis";
// Subscriber(購読側)
const sub = new Redis();
// Publisher(配信側)
const pub = new Redis();
sub.subscribe("notifications", (err, count) => {
if (err) {
console.error("Subscribe failed:", err);
return;
}
console.log(`Subscribed to ${count} channel(s)`);
});
sub.on("message", (channel: string, message: string) => {
console.log(`[${channel}] ${message}`);
// [notifications] {"type":"alert","body":"Hello!"}
});
// 別のインスタンスからメッセージを配信
setTimeout(async () => {
await pub.publish(
"notifications",
JSON.stringify({ type: "alert", body: "Hello!" })
);
}, 1000);
3. パイプライン(pipeline)
複数コマンドをまとめて送信し、ラウンドトリップを削減します。
import Redis from "ioredis";
const redis = new Redis();
async function pipelineExample() {
const pipeline = redis.pipeline();
pipeline.set("key1", "value1");
pipeline.set("key2", "value2");
pipeline.get("key1");
pipeline.get("key2");
// exec() で一括実行。結果は [error, result] のタプル配列
const results = await pipeline.exec();
console.log(results);
// [
// [null, "OK"],
// [null, "OK"],
// [null, "value1"],
// [null, "value2"],
// ]
await redis.quit();
}
pipelineExample();
4. トランザクション(multi / exec)
複数コマンドをアトミックに実行します。
import Redis from "ioredis";
const redis = new Redis();
async function transactionExample() {
// multi() でトランザクション開始
const results = await redis
.multi()
.set("account:A", "1000")
.set("account:B", "2000")
.decrby("account:A", 500)
.incrby("account:B", 500)
.exec();
// results: [[null, "OK"], [null, "OK"], [null, 500], [null, 2500]]
console.log(results);
const balanceA = await redis.get("account:A");
const balanceB = await redis.get("account:B");
console.log({ balanceA, balanceB }); // { balanceA: "500", balanceB: "2500" }
await redis.quit();
}
transactionExample();
5. Redis Cluster 接続
複数ノードで構成される Redis Cluster に接続する場合は Redis.Cluster を使います。
import Redis from "ioredis";
const cluster = new Redis.Cluster([
{ host: "redis-node-1", port: 6379 },
{ host: "redis-node-2", port: 6379 },
{ host: "redis-node-3", port: 6379 },
], {
// スロットリフレッシュの間隔(ミリ秒)
slotsRefreshTimeout: 2000,
redisOptions: {
password: "cluster-password",
},
});
async function clusterExample() {
await cluster.set("cluster-key", "hello from cluster");
const value = await cluster.get("cluster-key");
console.log(value); // "hello from cluster"
await cluster.quit();
}
clusterExample();
補足: Lua スクリプティング(defineCommand)
カスタムコマンドを定義してアトミックな操作を実現できます。
import Redis from "ioredis";
const redis = new Redis();
// カスタムコマンドを定義
redis.defineCommand("addAndGet", {
numberOfKeys: 1,
lua: `
local current = redis.call('get', KEYS[1])
if current == false then current = 0 end
local newVal = tonumber(current) + tonumber(ARGV[1])
redis.call('set', KEYS[1], newVal)
return newVal
`,
});
async function luaExample() {
await redis.set("counter", "10");
// defineCommand で定義したコマンドを呼び出し
// TypeScript では型アサーションが必要
const result = await (redis as any).addAndGet("counter", 5);
console.log(result); // 15
await redis.quit();
}
luaExample();
類似パッケージとの比較
| 項目 | ioredis | node-redis (redis) |
|---|---|---|
| メンテナンス状況 | 安定版(ベストエフォート) | 積極的に開発中(公式推奨) |
| TypeScript サポート | ✅ 同梱 | ✅ 同梱 |
| Cluster サポート | ✅ 組み込み | ✅ 組み込み |
| Sentinel サポート | ✅ 組み込み | ✅ 組み込み |
| Autopipelining | ✅ | ✅ |
| Redis Modules (JSON, Search 等) | ❌ 限定的 | ✅ ファーストクラスサポート |
| Redis 8 新機能対応 | ❌ | ✅ |
| Pub/Sub API | イベントベース(直感的) | 専用オブジェクト方式 |
| 利用実績 | Alibaba、BullMQ 等 | Redis 公式 |
| npm 週間DL数 | 非常に多い | 非常に多い |
選定の目安:
- 新規プロジェクトで Redis Stack / Redis 8 の機能を使いたい → node-redis
- BullMQ を使う / 既存プロジェクトで ioredis を利用中 → ioredis
- Cluster・Sentinel の実績重視 → ioredis(長年の安定実績)
注意点・Tips
1. Subscriber インスタンスは通常コマンドに使えない
subscribe() を呼んだインスタンスは Subscriber モードに入り、GET / SET などの通常コマンドを実行できなくなります。Pub/Sub 用と通常操作用でインスタンスを分けてください。
const sub = new Redis(); // Pub/Sub 専用
const redis = new Redis(); // 通常操作用
2. 接続エラーのハンドリング
ioredis はデフォルトで自動再接続しますが、エラーイベントのリスナーを必ず設定しましょう。リスナーがないと Node.js プロセスがクラッシュします。
const redis = new Redis({
retryStrategy(times) {
const delay = Math.min(times * 50, 2000);
return delay; // null を返すと再接続を停止
},
maxRetriesPerRequest: 3,
});
redis.on("error", (err) => {
console.error("Redis connection error:", err);
});
3. 戻り値はすべて文字列
Redis の GET 等で返る値は常に string | null です。数値を扱う場合は明示的にパースしてください。
await redis.set("count", "42");
const count = await redis.get("count"); // "42" (string)
const num = Number(count); // 42
4. keyPrefix で名前空間を分離
マルチテナントや環境分離に便利です。
const redis = new Redis({ keyPrefix: "myapp:" });
await redis.set("user:1", "Taro");
// 実際のキーは "myapp:user:1" になる
// ただし keys() や scan() には prefix が自動付与されないので注意
5. Autopipelining を活用する
enableAutoPipelining: true を設定すると、同一イベントループ内の複数コマンドが自動的にパイプライン化され、パフォーマンスが向上します。
const redis = new Redis({
enableAutoPipelining: true,
});
6. quit() と disconnect() の違い
quit()— 保留中のコマンドをすべて処理してから接続を閉じる(推奨)disconnect()— 即座に接続を切断する(保留中のコマンドはエラーになる)
まとめ
ioredis は、Node.js エコシステムにおいて長年使われてきた信頼性の高い Redis クライアントです。Cluster・Sentinel・Pipelining・Pub/Sub・Lua スクリプティングなど Redis の機能をフルに活用でき、TypeScript との相性も優れています。新規プロジェクトでは node-redis も検討すべきですが、BullMQ との組み合わせや既存資産の活用においては、ioredis は引き続き有力な選択肢です。