@@ -105,6 +105,10 @@ def _filter_cluster_hook(
105105 offset : int ,
106106 ** kwargs ,
107107 ) -> ResourceList :
108+ # 提前预取storage的tuple
109+ storage_queryset = storage_queryset .prefetch_related (
110+ "machine" , "nosqlstoragesetdtl_set" , "as_receiver" , "as_ejector"
111+ )
108112 # 预取remote的spec
109113 redis_spec_map = {spec .spec_id : spec for spec in Spec .objects .filter (spec_cluster_type = SpecClusterType .Redis )}
110114 return super ()._filter_cluster_hook (
@@ -132,9 +136,44 @@ def _to_cluster_representation(
132136 ** kwargs ,
133137 ) -> Dict [str , Any ]:
134138 """集群序列化"""
135- redis_master = [m .simple_desc for m in cluster .storages if m .instance_role == InstanceRole .REDIS_MASTER ]
136- redis_slave = [m .simple_desc for m in cluster .storages if m .instance_role == InstanceRole .REDIS_SLAVE ]
137- machine_list = list (set ([inst ["bk_host_id" ] for inst in [* redis_master , * redis_slave ]]))
139+ # 创建一个字典来存储 ejector_id 到cluster.storages下标的映射
140+ ejector_id__storage_map = {storage_instance .id : storage_instance for storage_instance in cluster .storages }
141+
142+ remote_infos = {InstanceRole .REDIS_MASTER .value : [], InstanceRole .REDIS_SLAVE .value : []}
143+ for inst in cluster .storages :
144+ try :
145+ seg_range = (
146+ inst .nosqlstoragesetdtl_set .all ()[0 ].seg_range
147+ if inst .cluster_type != ClusterType .RedisInstance .value
148+ else "-1"
149+ )
150+ except IndexError :
151+ # 异常处理 因nosqlstoragesetdtl的分片数据只有redis为master才有seg_range值 以下处理是slave找出对应master seg_range并赋予值 供主从对应排序处理
152+ master = ejector_id__storage_map .get (inst .as_receiver .all ()[0 ].ejector_id )
153+ seg_range = master .nosqlstoragesetdtl_set .all ()[0 ].seg_range if master is not None else "-1"
154+ except Exception :
155+ # 如果无法找到seg_range,则默认为-1。有可能实例处于restoring状态(比如集群容量变更时)
156+ seg_range = "-1"
157+
158+ remote_infos [inst .instance_role ].append ({** inst .simple_desc , "seg_range" : seg_range })
159+
160+ remote_infos [InstanceRole .REDIS_MASTER .value ].sort (
161+ key = lambda x : int (x .get ("seg_range" , "-1" ).split ("-" )[0 ]) if x .get ("seg_range" , "-1" ).split ("-" )[0 ] else - 1
162+ )
163+ remote_infos [InstanceRole .REDIS_SLAVE .value ].sort (
164+ key = lambda x : int (x .get ("seg_range" , "-1" ).split ("-" )[0 ]) if x .get ("seg_range" , "-1" ).split ("-" )[0 ] else - 1
165+ )
166+ machine_list = list (
167+ set (
168+ [
169+ inst ["bk_host_id" ]
170+ for inst in [
171+ * remote_infos [InstanceRole .REDIS_MASTER .value ],
172+ * remote_infos [InstanceRole .REDIS_SLAVE .value ],
173+ ]
174+ ]
175+ )
176+ )
138177 machine_pair_cnt = len (machine_list ) / 2
139178
140179 # 补充集群的规格和容量信息
@@ -163,9 +202,9 @@ def _to_cluster_representation(
163202 "cluster_capacity" : cluster_capacity ,
164203 "dns_to_clb" : dns_to_clb ,
165204 "proxy" : [m .simple_desc for m in cluster .proxies ],
166- "redis_master" : redis_master ,
167- "redis_slave" : redis_slave ,
168- "cluster_shard_num" : len (redis_master ),
205+ "redis_master" : remote_infos [ InstanceRole . REDIS_MASTER . value ] ,
206+ "redis_slave" : remote_infos [ InstanceRole . REDIS_SLAVE . value ] ,
207+ "cluster_shard_num" : len (remote_infos [ InstanceRole . REDIS_MASTER . value ] ),
169208 "machine_pair_cnt" : machine_pair_cnt ,
170209 "module_names" : module_names ,
171210 }
0 commit comments