0
# Redis Cluster Client
1
2
The RedisCluster class is the primary interface for interacting with Redis clusters. It extends the standard Redis client with cluster-aware implementations of Redis commands, automatic slot management, node discovery, and failover support.
3
4
## Capabilities
5
6
### RedisCluster Class
7
8
Main Redis cluster client that provides all standard Redis operations with cluster-aware implementations and additional cluster management functionality.
9
10
```python { .api }
11
class RedisCluster(Redis):
12
def __init__(self, host=None, port=None, startup_nodes=None,
13
max_connections=None, max_connections_per_node=False,
14
init_slot_cache=True, readonly_mode=False,
15
reinitialize_steps=None, skip_full_coverage_check=False,
16
nodemanager_follow_cluster=False, connection_class=None,
17
read_from_replicas=False, cluster_down_retry_attempts=3,
18
host_port_remap=None, **kwargs):
19
"""
20
Initialize Redis cluster client.
21
22
Parameters:
23
- host (str, optional): Single startup host
24
- port (int, optional): Port for single host
25
- startup_nodes (List[StartupNode], optional): List of initial cluster nodes
26
- max_connections (int, optional): Maximum total connections across cluster
27
- max_connections_per_node (bool|int): Enable per-node connection limits
28
- init_slot_cache (bool): Initialize slot-to-node mapping on startup
29
- readonly_mode (bool): Enable read-only operations
30
- reinitialize_steps (int, optional): Steps before reinitializing cluster layout
31
- skip_full_coverage_check (bool): Skip full cluster coverage validation
32
- nodemanager_follow_cluster (bool): Automatically follow cluster topology changes
33
- connection_class (type, optional): Custom connection class
34
- read_from_replicas (bool): Allow reading from replica nodes
35
- cluster_down_retry_attempts (int): Retry attempts for cluster-down errors
36
- host_port_remap (HostPortRemap, optional): Host/port remapping configuration
37
- **kwargs: Additional Redis connection parameters (decode_responses, etc.)
38
"""
39
```
40
41
### Client Creation
42
43
Create cluster clients from URLs or startup node lists.
44
45
```python { .api }
46
@classmethod
47
def from_url(cls, url, **kwargs):
48
"""
49
Create RedisCluster client from connection URL.
50
51
Parameters:
52
- url (str): Redis cluster URL (redis://host:port)
53
- **kwargs: Additional connection parameters
54
55
Returns:
56
RedisCluster: Configured cluster client instance
57
"""
58
```
59
60
### Core Client Methods
61
62
Essential client functionality for command execution and cluster interface creation.
63
64
```python { .api }
65
def execute_command(self, *args, **kwargs):
66
"""
67
Execute Redis command with cluster routing.
68
69
Parameters:
70
- *args: Command and arguments
71
- **kwargs: Additional execution options
72
73
Returns:
74
Any: Command result
75
"""
76
77
def pubsub(self, **kwargs):
78
"""
79
Get cluster-aware pub/sub interface.
80
81
Parameters:
82
- **kwargs: PubSub configuration options
83
84
Returns:
85
ClusterPubSub: Cluster pub/sub instance
86
"""
87
88
def pipeline(self, transaction=None, shard_hint=None, read_from_replicas=False):
89
"""
90
Create cluster pipeline for batching commands.
91
92
Parameters:
93
- transaction (bool, optional): Transaction mode (not supported in cluster)
94
- shard_hint (str, optional): Hint for pipeline routing
95
- read_from_replicas (bool): Enable reading from replicas
96
97
Returns:
98
ClusterPipeline: Pipeline instance for command batching
99
"""
100
```
101
102
### Key Scanning
103
104
Cluster-wide key iteration with pattern matching and type filtering.
105
106
```python { .api }
107
def scan_iter(self, match=None, count=None, _type=None):
108
"""
109
Scan keys across entire cluster.
110
111
Parameters:
112
- match (str, optional): Key pattern to match
113
- count (int, optional): Hint for number of keys per iteration
114
- _type (str, optional): Filter by key type
115
116
Yields:
117
str: Matching keys from all cluster nodes
118
"""
119
```
120
121
### Cluster Management Commands
122
123
Commands for managing cluster topology, slots, and node configuration.
124
125
```python { .api }
126
def cluster_info(self):
127
"""
128
Get cluster state information.
129
130
Returns:
131
dict: Cluster state details including size, slots, and status
132
"""
133
134
def cluster_nodes(self):
135
"""
136
Get detailed cluster topology information.
137
138
Returns:
139
dict: Node information including IDs, addresses, roles, and slot assignments
140
"""
141
142
def cluster_slots(self):
143
"""
144
Get hash slot to node mappings.
145
146
Returns:
147
SlotsMapping: List of slot ranges with assigned master and replica nodes
148
"""
149
150
def cluster_keyslot(self, name):
151
"""
152
Get hash slot for key.
153
154
Parameters:
155
- name (str): Key name
156
157
Returns:
158
int: Hash slot number (0-16383)
159
"""
160
161
def cluster_countkeysinslot(self, slot_id):
162
"""
163
Count keys in specific slot.
164
165
Parameters:
166
- slot_id (int): Slot number (0-16383)
167
168
Returns:
169
int: Number of keys in slot
170
"""
171
172
def cluster_count_failure_report(self, node_id):
173
"""
174
Get failure report count for specific node.
175
176
Parameters:
177
- node_id (str): Node ID to check failure reports for
178
179
Returns:
180
int: Number of failure reports for the node
181
"""
182
```
183
184
### Slot Management Commands
185
186
Commands for assigning and managing hash slots across cluster nodes.
187
188
```python { .api }
189
def cluster_addslots(self, node_id, *slots):
190
"""
191
Assign hash slots to specific node.
192
193
Parameters:
194
- node_id (str): Target node ID
195
- *slots (int): Slot numbers to assign
196
197
Returns:
198
bool: Success status
199
"""
200
201
def cluster_delslots(self, *slots):
202
"""
203
Remove hash slots from nodes.
204
205
Parameters:
206
- *slots (int): Slot numbers to remove
207
208
Returns:
209
bool: Success status
210
"""
211
```
212
213
### Node Management Commands
214
215
Commands for adding nodes, configuring replication, and managing cluster membership.
216
217
```python { .api }
218
def cluster_meet(self, node_id, host, port):
219
"""
220
Add node to cluster.
221
222
Parameters:
223
- node_id (str): Node ID to add
224
- host (str): Node hostname
225
- port (int): Node port
226
227
Returns:
228
bool: Success status
229
"""
230
231
def cluster_replicate(self, target_node_id):
232
"""
233
Configure current node as replica.
234
235
Parameters:
236
- target_node_id (str): Master node ID to replicate
237
238
Returns:
239
bool: Success status
240
"""
241
242
def cluster_failover(self, node_id, option=None):
243
"""
244
Force failover on specified node.
245
246
Parameters:
247
- node_id (str): Node ID to failover
248
- option (str, optional): Failover option ('FORCE' or 'TAKEOVER')
249
250
Returns:
251
bool: Success status
252
"""
253
254
def cluster_reset(self, node_id, soft=True):
255
"""
256
Reset cluster node.
257
258
Parameters:
259
- node_id (str): Node ID to reset
260
- soft (bool): Perform soft reset (preserve data)
261
262
Returns:
263
bool: Success status
264
"""
265
266
def cluster_reset_all_nodes(self, soft=True):
267
"""
268
Reset all cluster nodes.
269
270
Parameters:
271
- soft (bool): Perform soft reset (preserve data)
272
273
Returns:
274
bool: Success status
275
"""
276
277
def cluster_save_config(self):
278
"""
279
Save cluster configuration to disk.
280
281
Returns:
282
bool: Success status
283
"""
284
285
def cluster_get_keys_in_slot(self, slot, num_keys):
286
"""
287
Get keys in specific slot.
288
289
Parameters:
290
- slot (int): Slot number (0-16383)
291
- num_keys (int): Maximum number of keys to return
292
293
Returns:
294
List[str]: Keys in the slot
295
"""
296
297
def cluster_set_config_epoch(self, node_id, epoch):
298
"""
299
Set cluster configuration epoch for node.
300
301
Parameters:
302
- node_id (str): Node ID
303
- epoch (int): Configuration epoch
304
305
Returns:
306
bool: Success status
307
"""
308
309
def cluster_setslot(self, node_id, slot_id, state, bind_to_node_id=None):
310
"""
311
Set slot state for cluster reconfiguration.
312
313
Parameters:
314
- node_id (str): Node ID
315
- slot_id (int): Slot number (0-16383)
316
- state (str): Slot state ('IMPORTING', 'MIGRATING', 'STABLE', 'NODE')
317
- bind_to_node_id (str, optional): Node to bind slot to (for 'NODE' state)
318
319
Returns:
320
bool: Success status
321
"""
322
323
def cluster_slaves(self, target_node_id):
324
"""
325
Get slave nodes for specific master.
326
327
Parameters:
328
- target_node_id (str): Master node ID
329
330
Returns:
331
List[dict]: Slave node information
332
"""
333
```
334
335
### Cluster-Aware Redis Commands
336
337
Modified Redis commands that work across multiple cluster nodes.
338
339
```python { .api }
340
def mget(self, keys, *args):
341
"""
342
Multi-get across cluster nodes.
343
344
Parameters:
345
- keys (List[str]): List of keys to retrieve
346
- *args: Additional key arguments
347
348
Returns:
349
List[Any]: Values for requested keys (None for missing keys)
350
"""
351
352
def mset(self, *args, **kwargs):
353
"""
354
Multi-set across cluster nodes.
355
356
Parameters:
357
- *args: Key-value pairs as positional arguments
358
- **kwargs: Key-value pairs as keyword arguments
359
360
Returns:
361
bool: Success status
362
"""
363
364
def msetnx(self, *args, **kwargs):
365
"""
366
Multi-set if not exists across cluster nodes.
367
368
Parameters:
369
- *args: Key-value pairs as positional arguments
370
- **kwargs: Key-value pairs as keyword arguments
371
372
Returns:
373
bool: True if all keys were set, False otherwise
374
"""
375
376
def delete(self, *names):
377
"""
378
Delete multiple keys across cluster nodes.
379
380
Parameters:
381
- *names (str): Keys to delete
382
383
Returns:
384
int: Number of keys deleted
385
"""
386
387
def rename(self, src, dst, replace=False):
388
"""
389
Rename key with cross-slot support.
390
391
Parameters:
392
- src (str): Source key name
393
- dst (str): Destination key name
394
- replace (bool): Allow replacing existing destination key
395
396
Returns:
397
bool: Success status
398
"""
399
400
def renamenx(self, src, dst):
401
"""
402
Rename key if destination doesn't exist (cluster implementation is non-atomic).
403
404
Parameters:
405
- src (str): Source key name
406
- dst (str): Destination key name
407
408
Returns:
409
bool: True if rename occurred, False if destination already exists
410
411
Note:
412
In cluster mode, this operation is not atomic - it checks existence
413
then calls rename, which may cause race conditions.
414
"""
415
```
416
417
### Set Operations
418
419
Cluster-aware set operations that work across multiple nodes.
420
421
```python { .api }
422
def sdiff(self, keys, *args):
423
"""Set difference across cluster nodes."""
424
425
def sdiffstore(self, dest, keys, *args):
426
"""Store set difference result across cluster nodes."""
427
428
def sinter(self, keys, *args):
429
"""Set intersection across cluster nodes."""
430
431
def sinterstore(self, dest, keys, *args):
432
"""Store set intersection result across cluster nodes."""
433
434
def smove(self, src, dst, value):
435
"""Move set member between sets across cluster nodes."""
436
437
def sunion(self, keys, *args):
438
"""Set union across cluster nodes."""
439
440
def sunionstore(self, dest, keys, *args):
441
"""Store set union result across cluster nodes."""
442
```
443
444
### List Operations
445
446
Cluster-aware list operations for cross-slot list manipulation.
447
448
```python { .api }
449
def brpoplpush(self, src, dst, timeout=0):
450
"""
451
Blocking right pop left push across cluster nodes.
452
453
Parameters:
454
- src (str): Source list key
455
- dst (str): Destination list key
456
- timeout (int): Blocking timeout in seconds
457
458
Returns:
459
str: Moved element or None if timeout
460
"""
461
462
def rpoplpush(self, src, dst):
463
"""
464
Right pop left push across cluster nodes.
465
466
Parameters:
467
- src (str): Source list key
468
- dst (str): Destination list key
469
470
Returns:
471
str: Moved element or None if source empty
472
"""
473
```
474
475
### HyperLogLog Operations
476
477
Cluster-aware HyperLogLog operations for distributed cardinality estimation.
478
479
```python { .api }
480
def pfcount(self, *sources):
481
"""
482
Count unique elements across HyperLogLog keys.
483
484
Parameters:
485
- *sources (str): HyperLogLog key names
486
487
Returns:
488
int: Approximate cardinality
489
"""
490
491
def pfmerge(self, dest, *sources):
492
"""
493
Merge HyperLogLog keys across cluster nodes.
494
495
Parameters:
496
- dest (str): Destination key
497
- *sources (str): Source HyperLogLog keys
498
499
Returns:
500
bool: Success status
501
"""
502
```
503
504
### Pub/Sub Information Commands
505
506
Commands for getting information about active channels and subscriptions.
507
508
```python { .api }
509
def pubsub_channels(self, pattern='*', aggregate=True):
510
"""
511
Get list of channels with active subscribers.
512
513
Parameters:
514
- pattern (str): Channel name pattern to match
515
- aggregate (bool): Merge responses from all nodes
516
517
Returns:
518
List[str]: Active channel names matching pattern
519
"""
520
521
def pubsub_numpat(self, aggregate=True):
522
"""
523
Get number of active pattern subscriptions.
524
525
Parameters:
526
- aggregate (bool): Merge responses from all nodes
527
528
Returns:
529
int: Total number of pattern subscriptions
530
"""
531
532
def pubsub_numsub(self, *args, **kwargs):
533
"""
534
Get subscriber counts for specific channels.
535
536
Parameters:
537
- *args: Channel names to check
538
- aggregate (bool): Merge responses from all nodes (via kwargs)
539
540
Returns:
541
List[Tuple[str, int]]: Channel names and subscriber counts
542
"""
543
```
544
545
## Usage Examples
546
547
### Basic Client Setup
548
549
```python
550
from rediscluster import RedisCluster
551
552
# Single host startup
553
rc = RedisCluster(host='127.0.0.1', port=7000, decode_responses=True)
554
555
# Multiple startup nodes for redundancy
556
startup_nodes = [
557
{"host": "127.0.0.1", "port": "7000"},
558
{"host": "127.0.0.1", "port": "7001"},
559
{"host": "127.0.0.1", "port": "7002"}
560
]
561
rc = RedisCluster(startup_nodes=startup_nodes, decode_responses=True)
562
563
# From URL
564
rc = RedisCluster.from_url("redis://127.0.0.1:7000", decode_responses=True)
565
```
566
567
### Advanced Configuration
568
569
```python
570
# Production configuration with connection pooling
571
rc = RedisCluster(
572
startup_nodes=startup_nodes,
573
decode_responses=True,
574
max_connections=32,
575
max_connections_per_node=8,
576
read_from_replicas=True,
577
cluster_down_retry_attempts=5,
578
socket_timeout=5,
579
socket_connect_timeout=5
580
)
581
582
# Read-only replica configuration
583
rc = RedisCluster(
584
startup_nodes=startup_nodes,
585
readonly_mode=True,
586
read_from_replicas=True
587
)
588
```
589
590
### Cluster Management
591
592
```python
593
# Get cluster information
594
info = rc.cluster_info()
595
print(f"Cluster size: {info['cluster_size']}")
596
print(f"Cluster state: {info['cluster_state']}")
597
598
# Get node topology
599
nodes = rc.cluster_nodes()
600
for node_id, node_info in nodes.items():
601
print(f"Node {node_id}: {node_info['host']}:{node_info['port']} - {node_info['role']}")
602
603
# Get slot mappings
604
slots = rc.cluster_slots()
605
for slot_range in slots:
606
start_slot, end_slot = slot_range[0], slot_range[1]
607
master = slot_range[2]
608
print(f"Slots {start_slot}-{end_slot}: master {master[0]}:{master[1]}")
609
```
610
611
### Multi-Key Operations
612
613
```python
614
# Multi-key operations work transparently across nodes
615
keys_values = {"user:1": "data1", "user:2": "data2", "session:abc": "active"}
616
rc.mset(keys_values)
617
618
values = rc.mget(["user:1", "user:2", "session:abc"])
619
print(values) # ['data1', 'data2', 'active']
620
621
# Delete multiple keys
622
deleted = rc.delete("user:1", "user:2", "session:abc")
623
print(f"Deleted {deleted} keys")
624
```