0
# Cluster Operations
1
2
Redis Cluster client provides automatic slot management, node discovery, failover handling, and load distribution across multiple Redis nodes. It maintains compatibility with the Redis client API while adding cluster-specific functionality.
3
4
## Capabilities
5
6
### Cluster Class
7
8
Main client class for Redis Cluster deployments with automatic slot mapping and node management.
9
10
```typescript { .api }
11
class Cluster extends EventEmitter {
12
constructor(startupNodes: ClusterNode[], options?: ClusterOptions);
13
14
// Connection management
15
connect(): Promise<void>;
16
disconnect(reconnect?: boolean): void;
17
quit(callback?: Callback<"OK">): Promise<"OK">;
18
duplicate(overrideStartupNodes?: ClusterNode[], overrideOptions?: ClusterOptions): Cluster;
19
20
// Properties
21
readonly options: ClusterOptions;
22
readonly status: ClusterStatus;
23
readonly autoPipelineQueueSize: number;
24
25
// Cluster management
26
nodes(role?: NodeRole): Redis[];
27
refreshSlotsCache(callback?: Callback<void>): void;
28
29
// All Redis commands are available with automatic slot routing
30
}
31
32
type ClusterNode = string | number | {
33
host?: string;
34
port?: number;
35
};
36
37
type ClusterStatus = "wait" | "reconnecting" | "connecting" | "connect" | "ready" | "close" | "end";
38
type NodeRole = "master" | "slave" | "all";
39
```
40
41
**Usage Examples:**
42
43
```typescript
44
import { Cluster } from "ioredis";
45
46
// Basic cluster connection
47
const cluster = new Cluster([
48
{ host: "127.0.0.1", port: 7000 },
49
{ host: "127.0.0.1", port: 7001 },
50
{ host: "127.0.0.1", port: 7002 }
51
]);
52
53
// Connection with options
54
const cluster2 = new Cluster([
55
"127.0.0.1:7000",
56
"127.0.0.1:7001",
57
"127.0.0.1:7002"
58
], {
59
scaleReads: "slave",
60
maxRedirections: 16,
61
retryStrategy: (times) => Math.min(times * 50, 2000)
62
});
63
64
// Automatic Redis command routing
65
await cluster.set("key", "value");
66
const value = await cluster.get("key");
67
```
68
69
### Node Management
70
71
Access and manage individual Redis nodes within the cluster.
72
73
```typescript { .api }
74
// Get nodes by role
75
nodes(role?: NodeRole): Redis[];
76
77
// Refresh slot mapping from cluster
78
refreshSlotsCache(callback?: Callback<void>): void;
79
```
80
81
**Usage Examples:**
82
83
```typescript
84
// Get all master nodes
85
const masters = cluster.nodes("master");
86
console.log(`${masters.length} master nodes`);
87
88
// Get all slave nodes
89
const slaves = cluster.nodes("slave");
90
91
// Get all nodes
92
const allNodes = cluster.nodes("all");
93
94
// Manual slot cache refresh
95
cluster.refreshSlotsCache((err) => {
96
if (err) console.error("Failed to refresh slots:", err);
97
else console.log("Slots cache refreshed");
98
});
99
```
100
101
### Cluster Configuration
102
103
Comprehensive configuration options extending Redis options with cluster-specific settings.
104
105
```typescript { .api }
106
interface ClusterOptions extends Partial<RedisOptions> {
107
// Cluster behavior
108
clusterRetryStrategy?: (times: number, reason?: Error) => number | void | null;
109
enableOfflineQueue?: boolean;
110
redisOptions?: RedisOptions;
111
scaleReads?: NodeRole | ((node: any, command: any) => Redis);
112
113
// Slot management
114
maxRedirections?: number;
115
retryDelayOnClusterDown?: number;
116
retryDelayOnMove?: number;
117
retryDelayOnFailover?: number;
118
119
// Node discovery
120
enableReadyCheck?: boolean;
121
lazyConnect?: boolean;
122
dnsLookup?: DNSLookupFunction;
123
124
// Performance
125
enableAutoPipelining?: boolean;
126
autoPipeliningIgnoredCommands?: string[];
127
128
// NAT support
129
natMap?: NatMap;
130
131
// Custom slot calculation
132
keyHashTag?: string;
133
134
// Cluster commands
135
customCommandHandlers?: Record<string, (command: string, args: any[]) => void>;
136
}
137
138
interface NatMap {
139
[key: string]: { host: string; port: number };
140
}
141
```
142
143
**Usage Examples:**
144
145
```typescript
146
const cluster = new Cluster([
147
{ host: "127.0.0.1", port: 7000 }
148
], {
149
// Read from slave nodes when possible
150
scaleReads: "slave",
151
152
// Cluster retry strategy
153
clusterRetryStrategy: (times, reason) => {
154
console.log(`Cluster retry ${times}: ${reason?.message}`);
155
return times < 10 ? Math.min(times * 100, 5000) : null;
156
},
157
158
// Max redirections before giving up
159
maxRedirections: 16,
160
161
// Enable autopipelining for performance
162
enableAutoPipelining: true,
163
164
// Custom Redis options for each node
165
redisOptions: {
166
password: "cluster-password",
167
connectTimeout: 5000,
168
commandTimeout: 2000
169
},
170
171
// NAT mapping for Docker/cloud environments
172
natMap: {
173
"172.17.0.2:7000": { host: "redis-node-1.example.com", port: 7000 },
174
"172.17.0.3:7001": { host: "redis-node-2.example.com", port: 7001 }
175
}
176
});
177
```
178
179
### Cluster Events
180
181
The Cluster client emits events for connection lifecycle and cluster state changes.
182
183
```typescript { .api }
184
// Connection events (inherited from EventEmitter)
185
on(event: 'connect', listener: (address?: string) => void): this;
186
on(event: 'ready', listener: () => void): this;
187
on(event: 'error', listener: (err: Error) => void): this;
188
on(event: 'close', listener: () => void): this;
189
on(event: 'reconnecting', listener: (ms: number) => void): this;
190
on(event: 'end', listener: () => void): this;
191
192
// Cluster-specific events
193
on(event: 'node error', listener: (err: Error, address: string) => void): this;
194
on(event: '+node', listener: (address: string) => void): this;
195
on(event: '-node', listener: (address: string) => void): this;
196
```
197
198
**Usage Examples:**
199
200
```typescript
201
const cluster = new Cluster([{ host: "127.0.0.1", port: 7000 }]);
202
203
cluster.on('ready', () => {
204
console.log('Cluster is ready');
205
});
206
207
cluster.on('error', (err) => {
208
console.error('Cluster error:', err);
209
});
210
211
cluster.on('node error', (err, address) => {
212
console.error(`Node ${address} error:`, err);
213
});
214
215
cluster.on('+node', (address) => {
216
console.log(`Node added: ${address}`);
217
});
218
219
cluster.on('-node', (address) => {
220
console.log(`Node removed: ${address}`);
221
});
222
```
223
224
## Advanced Features
225
226
### Custom Scale Reads Function
227
228
Implement custom logic for directing read commands to specific nodes.
229
230
```typescript { .api }
231
type ScaleReadsFunction = (node: {
232
role: string;
233
key: string;
234
options: any;
235
}, command: {
236
name: string;
237
args: any[];
238
}) => Redis | null;
239
```
240
241
```typescript
242
const cluster = new Cluster(nodes, {
243
scaleReads: (node, command) => {
244
// Direct specific commands to masters only
245
if (['eval', 'evalsha'].includes(command.name.toLowerCase())) {
246
return node.role === 'master' ? node : null;
247
}
248
// Use slaves for read operations
249
return node.role === 'slave' ? node : null;
250
}
251
});
252
```
253
254
### Cluster Connection Duplication
255
256
Create new cluster instances with independent connections but shared configuration.
257
258
```typescript { .api }
259
duplicate(
260
overrideStartupNodes?: ClusterNode[],
261
overrideOptions?: ClusterOptions
262
): Cluster;
263
```
264
265
```typescript
266
const originalCluster = new Cluster([...nodes], options);
267
268
// Duplicate with same configuration
269
const dup1 = originalCluster.duplicate();
270
271
// Duplicate with different nodes
272
const dup2 = originalCluster.duplicate([
273
{ host: "new-cluster-1.example.com", port: 7000 }
274
]);
275
276
// Duplicate with different options
277
const dup3 = originalCluster.duplicate(undefined, {
278
scaleReads: "master",
279
maxRedirections: 8
280
});
281
```
282
283
## Types
284
285
```typescript { .api }
286
type Callback<T> = (err?: Error | null, result?: T) => void;
287
288
interface DNSLookupFunction {
289
(hostname: string, options: any, callback: Function): void;
290
}
291
```