2323import java .util .ArrayList ;
2424import java .util .Collections ;
2525import java .util .List ;
26+ import java .util .concurrent .ThreadLocalRandom ;
2627
2728public class ObPartitionLocation {
2829 private ReplicaLocation leader ;
@@ -90,10 +91,9 @@ public ReplicaLocation getReplica(ObReadConsistency consistencyLevel,
9091 }
9192
9293 private ReplicaLocation getReadReplicaNoLdc (ObRoutePolicy routePolicy ) {
93- for (ReplicaLocation r : replicas ) {
94- if (r .isValid () && !r .isLeader ()) {
95- return r ;
96- }
94+ ReplicaLocation follower = getRandomFollowerFromList (replicas );
95+ if (follower != null ) {
96+ return follower ;
9797 }
9898 if (routePolicy == ObRoutePolicy .FOLLOWER_ONLY ) {
9999 throw new IllegalArgumentException ("No follower replica found for route policy: "
@@ -107,25 +107,22 @@ private ReplicaLocation getReadReplicaByRoutePolicy(ObRoutePolicy routePolicy)
107107 // 路由策略优先:FOLLOWER_FIRST 优先选择 follower,FOLLOWER_ONLY 只能选择 follower
108108 // 在满足路由策略的前提下,按就近原则选择(同机房 -> 同 region -> 其他 region)
109109
110- // 优先在同机房找 follower
111- for (ReplicaLocation r : sameIdc ) {
112- if (r .isValid () && !r .isLeader ()) {
113- return r ;
114- }
110+ // 优先在同机房找 follower(随机选择以避免热点)
111+ ReplicaLocation follower = getRandomFollowerFromList (sameIdc );
112+ if (follower != null ) {
113+ return follower ;
115114 }
116115
117- // 如果同机房没有 follower,在同 region 找 follower
118- for (ReplicaLocation r : sameRegion ) {
119- if (r .isValid () && !r .isLeader ()) {
120- return r ;
121- }
116+ // 如果同机房没有 follower,在同 region 找 follower(随机选择以避免热点)
117+ follower = getRandomFollowerFromList (sameRegion );
118+ if (follower != null ) {
119+ return follower ;
122120 }
123121
124- // 如果同 region 没有 follower,在其他 region 找 follower
125- for (ReplicaLocation r : otherRegion ) {
126- if (r .isValid () && !r .isLeader ()) {
127- return r ;
128- }
122+ // 如果同 region 没有 follower,在其他 region 找 follower(随机选择以避免热点)
123+ follower = getRandomFollowerFromList (otherRegion );
124+ if (follower != null ) {
125+ return follower ;
129126 }
130127
131128 // 如果都没有找到 follower
@@ -139,6 +136,33 @@ private ReplicaLocation getReadReplicaByRoutePolicy(ObRoutePolicy routePolicy)
139136 return leader ;
140137 }
141138
139+ /**
140+ * 从列表中随机选择一个有效的 follower,避免热点问题
141+ *
142+ * @param locations replica 列表
143+ * @return 随机选择的 follower,如果没有有效的 follower 则返回 null
144+ */
145+ private ReplicaLocation getRandomFollowerFromList (List <ReplicaLocation > locations ) {
146+ if (locations == null || locations .isEmpty ()) {
147+ return null ;
148+ }
149+
150+ // 收集所有有效的 follower
151+ List <ReplicaLocation > validFollowers = new ArrayList <>();
152+ for (ReplicaLocation r : locations ) {
153+ if (r .isValid () && !r .isLeader ()) {
154+ validFollowers .add (r );
155+ }
156+ }
157+
158+ if (validFollowers .isEmpty ()) {
159+ return null ;
160+ }
161+
162+ // 随机选择一个 follower
163+ return validFollowers .get (ThreadLocalRandom .current ().nextInt (validFollowers .size ()));
164+ }
165+
142166 /*
143167 * Classify Replica for weak read, according to Server LDC location.
144168 * Synchronized to avoid duplicate initialization.
0 commit comments