44
44
import org .opensearch .common .settings .Setting ;
45
45
import org .opensearch .common .settings .Setting .Property ;
46
46
import org .opensearch .common .settings .Settings ;
47
+ import org .opensearch .common .util .FeatureFlags ;
47
48
import org .opensearch .node .remotestore .RemoteStoreNodeService ;
48
49
49
50
import java .util .Map ;
@@ -88,6 +89,8 @@ public class FilterAllocationDecider extends AllocationDecider {
88
89
private static final String CLUSTER_ROUTING_REQUIRE_GROUP_PREFIX = "cluster.routing.allocation.require" ;
89
90
private static final String CLUSTER_ROUTING_INCLUDE_GROUP_PREFIX = "cluster.routing.allocation.include" ;
90
91
private static final String CLUSTER_ROUTING_EXCLUDE_GROUP_PREFIX = "cluster.routing.allocation.exclude" ;
92
+ private static final String SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_PREFIX = "cluster.routing.allocation.search.replica.dedicated.include" ;
93
+
91
94
public static final Setting .AffixSetting <String > CLUSTER_ROUTING_REQUIRE_GROUP_SETTING = Setting .prefixKeySetting (
92
95
CLUSTER_ROUTING_REQUIRE_GROUP_PREFIX + "." ,
93
96
key -> Setting .simpleString (key , value -> IP_VALIDATOR .accept (key , value ), Property .Dynamic , Property .NodeScope )
@@ -100,7 +103,12 @@ public class FilterAllocationDecider extends AllocationDecider {
100
103
CLUSTER_ROUTING_EXCLUDE_GROUP_PREFIX + "." ,
101
104
key -> Setting .simpleString (key , value -> IP_VALIDATOR .accept (key , value ), Property .Dynamic , Property .NodeScope )
102
105
);
106
+ public static final Setting .AffixSetting <String > SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_SETTING = Setting .prefixKeySetting (
107
+ SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_PREFIX + "." ,
108
+ key -> Setting .simpleString (key , value -> IP_VALIDATOR .accept (key , value ), Property .Dynamic , Property .NodeScope )
109
+ );
103
110
111
+ private volatile DiscoveryNodeFilters searchReplicaIncludeFilters ;
104
112
private volatile DiscoveryNodeFilters clusterRequireFilters ;
105
113
private volatile DiscoveryNodeFilters clusterIncludeFilters ;
106
114
private volatile DiscoveryNodeFilters clusterExcludeFilters ;
@@ -113,7 +121,6 @@ public FilterAllocationDecider(Settings settings, ClusterSettings clusterSetting
113
121
setClusterIncludeFilters (CLUSTER_ROUTING_INCLUDE_GROUP_SETTING .getAsMap (settings ));
114
122
this .migrationDirection = RemoteStoreNodeService .MIGRATION_DIRECTION_SETTING .get (settings );
115
123
this .compatibilityMode = RemoteStoreNodeService .REMOTE_STORE_COMPATIBILITY_MODE_SETTING .get (settings );
116
-
117
124
clusterSettings .addAffixMapUpdateConsumer (CLUSTER_ROUTING_REQUIRE_GROUP_SETTING , this ::setClusterRequireFilters , (a , b ) -> {});
118
125
clusterSettings .addAffixMapUpdateConsumer (CLUSTER_ROUTING_EXCLUDE_GROUP_SETTING , this ::setClusterExcludeFilters , (a , b ) -> {});
119
126
clusterSettings .addAffixMapUpdateConsumer (CLUSTER_ROUTING_INCLUDE_GROUP_SETTING , this ::setClusterIncludeFilters , (a , b ) -> {});
@@ -122,6 +129,15 @@ public FilterAllocationDecider(Settings settings, ClusterSettings clusterSetting
122
129
RemoteStoreNodeService .REMOTE_STORE_COMPATIBILITY_MODE_SETTING ,
123
130
this ::setCompatibilityMode
124
131
);
132
+
133
+ if (FeatureFlags .isEnabled (FeatureFlags .READER_WRITER_SPLIT_EXPERIMENTAL )) {
134
+ setSearchReplicaIncludeFilters (SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_SETTING .getAsMap (settings ));
135
+ clusterSettings .addAffixMapUpdateConsumer (
136
+ SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_SETTING ,
137
+ this ::setSearchReplicaIncludeFilters ,
138
+ (a , b ) -> {}
139
+ );
140
+ }
125
141
}
126
142
127
143
private void setMigrationDirection (RemoteStoreNodeService .Direction migrationDirection ) {
@@ -203,6 +219,9 @@ private Decision shouldFilter(ShardRouting shardRouting, DiscoveryNode node, Rou
203
219
decision = shouldIndexFilter (allocation .metadata ().getIndexSafe (shardRouting .index ()), node , allocation );
204
220
if (decision != null ) return decision ;
205
221
222
+ decision = shouldSearchReplicaShardTypeFilter (shardRouting , node , allocation );
223
+ if (decision != null ) return decision ;
224
+
206
225
return allocation .decision (Decision .YES , NAME , "node passes include/exclude/require filters" );
207
226
}
208
227
@@ -294,6 +313,32 @@ private Decision shouldClusterFilter(DiscoveryNode node, RoutingAllocation alloc
294
313
return null ;
295
314
}
296
315
316
+ private Decision shouldSearchReplicaShardTypeFilter (ShardRouting routing , DiscoveryNode node , RoutingAllocation allocation ) {
317
+ if (searchReplicaIncludeFilters != null ) {
318
+ final boolean match = searchReplicaIncludeFilters .match (node );
319
+ if (match == false && routing .isSearchOnly ()) {
320
+ return allocation .decision (
321
+ Decision .NO ,
322
+ NAME ,
323
+ "node does not match shard setting [%s] filters [%s]" ,
324
+ SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_PREFIX ,
325
+ searchReplicaIncludeFilters
326
+ );
327
+ }
328
+ // filter will only apply to search replicas
329
+ if (routing .isSearchOnly () == false && match ) {
330
+ return allocation .decision (
331
+ Decision .NO ,
332
+ NAME ,
333
+ "only search replicas can be allocated to node with setting [%s] filters [%s]" ,
334
+ SEARCH_REPLICA_ROUTING_INCLUDE_GROUP_PREFIX ,
335
+ searchReplicaIncludeFilters
336
+ );
337
+ }
338
+ }
339
+ return null ;
340
+ }
341
+
297
342
private void setClusterRequireFilters (Map <String , String > filters ) {
298
343
clusterRequireFilters = DiscoveryNodeFilters .trimTier (
299
344
DiscoveryNodeFilters .buildOrUpdateFromKeyValue (clusterRequireFilters , AND , filters )
@@ -311,4 +356,10 @@ private void setClusterExcludeFilters(Map<String, String> filters) {
311
356
DiscoveryNodeFilters .buildOrUpdateFromKeyValue (clusterExcludeFilters , OR , filters )
312
357
);
313
358
}
359
+
360
+ private void setSearchReplicaIncludeFilters (Map <String , String > filters ) {
361
+ searchReplicaIncludeFilters = DiscoveryNodeFilters .trimTier (
362
+ DiscoveryNodeFilters .buildOrUpdateFromKeyValue (searchReplicaIncludeFilters , OR , filters )
363
+ );
364
+ }
314
365
}
0 commit comments