@@ -134,6 +134,14 @@ class RedisCluster(AbstractRedis, AbstractRedisCluster, AsyncRedisClusterCommand
134
134
| Enable read from replicas in READONLY mode and defines the load balancing
135
135
strategy that will be used for cluster node selection.
136
136
The data read from replicas is eventually consistent with the data in primary nodes.
137
+ :param dynamic_startup_nodes:
138
+ | Set the RedisCluster's startup nodes to all the discovered nodes.
139
+ If true (default value), the cluster's discovered nodes will be used to
140
+ determine the cluster nodes-slots mapping in the next topology refresh.
141
+ It will remove the initial passed startup nodes if their endpoints aren't
142
+ listed in the CLUSTER SLOTS output.
143
+ If you use dynamic DNS endpoints for startup nodes but CLUSTER SLOTS lists
144
+ specific IP addresses, it is best to set it to false.
137
145
:param reinitialize_steps:
138
146
| Specifies the number of MOVED errors that need to occur before reinitializing
139
147
the whole cluster topology. If a MOVED error occurs and the cluster does not
@@ -250,6 +258,7 @@ def __init__(
250
258
require_full_coverage : bool = True ,
251
259
read_from_replicas : bool = False ,
252
260
load_balancing_strategy : Optional [LoadBalancingStrategy ] = None ,
261
+ dynamic_startup_nodes : bool = True ,
253
262
reinitialize_steps : int = 5 ,
254
263
cluster_error_retry_attempts : int = 3 ,
255
264
max_connections : int = 2 ** 31 ,
@@ -388,6 +397,7 @@ def __init__(
388
397
startup_nodes ,
389
398
require_full_coverage ,
390
399
kwargs ,
400
+ dynamic_startup_nodes = dynamic_startup_nodes ,
391
401
address_remap = address_remap ,
392
402
event_dispatcher = self ._event_dispatcher ,
393
403
)
@@ -1162,6 +1172,7 @@ async def _mock(self, error: RedisError):
1162
1172
1163
1173
class NodesManager :
1164
1174
__slots__ = (
1175
+ "_dynamic_startup_nodes" ,
1165
1176
"_moved_exception" ,
1166
1177
"_event_dispatcher" ,
1167
1178
"connection_kwargs" ,
@@ -1179,6 +1190,7 @@ def __init__(
1179
1190
startup_nodes : List ["ClusterNode" ],
1180
1191
require_full_coverage : bool ,
1181
1192
connection_kwargs : Dict [str , Any ],
1193
+ dynamic_startup_nodes : bool = True ,
1182
1194
address_remap : Optional [Callable [[Tuple [str , int ]], Tuple [str , int ]]] = None ,
1183
1195
event_dispatcher : Optional [EventDispatcher ] = None ,
1184
1196
) -> None :
@@ -1191,6 +1203,8 @@ def __init__(
1191
1203
self .nodes_cache : Dict [str , "ClusterNode" ] = {}
1192
1204
self .slots_cache : Dict [int , List ["ClusterNode" ]] = {}
1193
1205
self .read_load_balancer = LoadBalancer ()
1206
+
1207
+ self ._dynamic_startup_nodes : bool = dynamic_startup_nodes
1194
1208
self ._moved_exception : MovedError = None
1195
1209
if event_dispatcher is None :
1196
1210
self ._event_dispatcher = EventDispatcher ()
@@ -1433,8 +1447,10 @@ async def initialize(self) -> None:
1433
1447
# Set the tmp variables to the real variables
1434
1448
self .slots_cache = tmp_slots
1435
1449
self .set_nodes (self .nodes_cache , tmp_nodes_cache , remove_old = True )
1436
- # Populate the startup nodes with all discovered nodes
1437
- self .set_nodes (self .startup_nodes , self .nodes_cache , remove_old = True )
1450
+
1451
+ if self ._dynamic_startup_nodes :
1452
+ # Populate the startup nodes with all discovered nodes
1453
+ self .set_nodes (self .startup_nodes , self .nodes_cache , remove_old = True )
1438
1454
1439
1455
# Set the default node
1440
1456
self .default_node = self .get_nodes_by_server_type (PRIMARY )[0 ]
0 commit comments