34
34
import org .apache .hadoop .hbase .client .RegionReplicaUtil ;
35
35
import org .apache .hadoop .hbase .master .RackManager ;
36
36
import org .apache .hadoop .hbase .net .Address ;
37
+ import org .apache .hadoop .hbase .util .Pair ;
37
38
import org .apache .yetus .audience .InterfaceAudience ;
38
39
import org .slf4j .Logger ;
39
40
import org .slf4j .LoggerFactory ;
@@ -114,6 +115,12 @@ class BalancerClusterState {
114
115
private float [][] rackLocalities ;
115
116
// Maps localityType -> region -> [server|rack]Index with highest locality
116
117
private int [][] regionsToMostLocalEntities ;
118
+ // Maps region -> serverIndex -> regionCacheRatio of a region on a server
119
+ private Map <Pair <Integer , Integer >, Float > regionIndexServerIndexRegionCachedRatio ;
120
+ // Maps regionIndex -> serverIndex with best region cache ratio
121
+ private int [] regionServerIndexWithBestRegionCachedRatio ;
122
+ // Maps regionName -> oldServerName -> cache ratio of the region on the old server
123
+ Map <String , Pair <ServerName , Float >> regionCacheRatioOnOldServerMap ;
117
124
118
125
static class DefaultRackManager extends RackManager {
119
126
@ Override
@@ -125,13 +132,20 @@ public String getRack(ServerName server) {
125
132
BalancerClusterState (Map <ServerName , List <RegionInfo >> clusterState ,
126
133
Map <String , Deque <BalancerRegionLoad >> loads , RegionHDFSBlockLocationFinder regionFinder ,
127
134
RackManager rackManager ) {
128
- this (null , clusterState , loads , regionFinder , rackManager );
135
+ this (null , clusterState , loads , regionFinder , rackManager , null );
136
+ }
137
+
138
+ protected BalancerClusterState (Map <ServerName , List <RegionInfo >> clusterState ,
139
+ Map <String , Deque <BalancerRegionLoad >> loads , RegionHDFSBlockLocationFinder regionFinder ,
140
+ RackManager rackManager , Map <String , Pair <ServerName , Float >> oldRegionServerRegionCacheRatio ) {
141
+ this (null , clusterState , loads , regionFinder , rackManager , oldRegionServerRegionCacheRatio );
129
142
}
130
143
131
144
@ SuppressWarnings ("unchecked" )
132
145
BalancerClusterState (Collection <RegionInfo > unassignedRegions ,
133
146
Map <ServerName , List <RegionInfo >> clusterState , Map <String , Deque <BalancerRegionLoad >> loads ,
134
- RegionHDFSBlockLocationFinder regionFinder , RackManager rackManager ) {
147
+ RegionHDFSBlockLocationFinder regionFinder , RackManager rackManager ,
148
+ Map <String , Pair <ServerName , Float >> oldRegionServerRegionCacheRatio ) {
135
149
if (unassignedRegions == null ) {
136
150
unassignedRegions = Collections .emptyList ();
137
151
}
@@ -145,6 +159,8 @@ public String getRack(ServerName server) {
145
159
tables = new ArrayList <>();
146
160
this .rackManager = rackManager != null ? rackManager : new DefaultRackManager ();
147
161
162
+ this .regionCacheRatioOnOldServerMap = oldRegionServerRegionCacheRatio ;
163
+
148
164
numRegions = 0 ;
149
165
150
166
List <List <Integer >> serversPerHostList = new ArrayList <>();
@@ -541,6 +557,142 @@ private void computeCachedLocalities() {
541
557
542
558
}
543
559
560
+ /**
561
+ * Returns the size of hFiles from the most recent RegionLoad for region
562
+ */
563
+ public int getTotalRegionHFileSizeMB (int region ) {
564
+ Deque <BalancerRegionLoad > load = regionLoads [region ];
565
+ if (load == null ) {
566
+ // This means, that the region has no actual data on disk
567
+ return 0 ;
568
+ }
569
+ return regionLoads [region ].getLast ().getRegionSizeMB ();
570
+ }
571
+
572
+ /**
573
+ * Returns the weighted cache ratio of a region on the given region server
574
+ */
575
+ public float getOrComputeWeightedRegionCacheRatio (int region , int server ) {
576
+ return getTotalRegionHFileSizeMB (region ) * getOrComputeRegionCacheRatio (region , server );
577
+ }
578
+
579
+ /**
580
+ * Returns the amount by which a region is cached on a given region server. If the region is not
581
+ * currently hosted on the given region server, then find out if it was previously hosted there
582
+ * and return the old cache ratio.
583
+ */
584
+ protected float getRegionCacheRatioOnRegionServer (int region , int regionServerIndex ) {
585
+ float regionCacheRatio = 0.0f ;
586
+
587
+ // Get the current region cache ratio if the region is hosted on the server regionServerIndex
588
+ for (int regionIndex : regionsPerServer [regionServerIndex ]) {
589
+ if (region != regionIndex ) {
590
+ continue ;
591
+ }
592
+
593
+ Deque <BalancerRegionLoad > regionLoadList = regionLoads [regionIndex ];
594
+
595
+ // The region is currently hosted on this region server. Get the region cache ratio for this
596
+ // region on this server
597
+ regionCacheRatio =
598
+ regionLoadList == null ? 0.0f : regionLoadList .getLast ().getCurrentRegionCacheRatio ();
599
+
600
+ return regionCacheRatio ;
601
+ }
602
+
603
+ // Region is not currently hosted on this server. Check if the region was cached on this
604
+ // server earlier. This can happen when the server was shutdown and the cache was persisted.
605
+ // Search using the region name and server name and not the index id and server id as these ids
606
+ // may change when a server is marked as dead or a new server is added.
607
+ String regionEncodedName = regions [region ].getEncodedName ();
608
+ ServerName serverName = servers [regionServerIndex ];
609
+ if (
610
+ regionCacheRatioOnOldServerMap != null
611
+ && regionCacheRatioOnOldServerMap .containsKey (regionEncodedName )
612
+ ) {
613
+ Pair <ServerName , Float > cacheRatioOfRegionOnServer =
614
+ regionCacheRatioOnOldServerMap .get (regionEncodedName );
615
+ if (ServerName .isSameAddress (cacheRatioOfRegionOnServer .getFirst (), serverName )) {
616
+ regionCacheRatio = cacheRatioOfRegionOnServer .getSecond ();
617
+ if (LOG .isDebugEnabled ()) {
618
+ LOG .debug ("Old cache ratio found for region {} on server {}: {}" , regionEncodedName ,
619
+ serverName , regionCacheRatio );
620
+ }
621
+ }
622
+ }
623
+ return regionCacheRatio ;
624
+ }
625
+
626
+ /**
627
+ * Populate the maps containing information about how much a region is cached on a region server.
628
+ */
629
+ private void computeRegionServerRegionCacheRatio () {
630
+ regionIndexServerIndexRegionCachedRatio = new HashMap <>();
631
+ regionServerIndexWithBestRegionCachedRatio = new int [numRegions ];
632
+
633
+ for (int region = 0 ; region < numRegions ; region ++) {
634
+ float bestRegionCacheRatio = 0.0f ;
635
+ int serverWithBestRegionCacheRatio = 0 ;
636
+ for (int server = 0 ; server < numServers ; server ++) {
637
+ float regionCacheRatio = getRegionCacheRatioOnRegionServer (region , server );
638
+ if (regionCacheRatio > 0.0f || server == regionIndexToServerIndex [region ]) {
639
+ // A region with cache ratio 0 on a server means nothing. Hence, just make a note of
640
+ // cache ratio only if the cache ratio is greater than 0.
641
+ Pair <Integer , Integer > regionServerPair = new Pair <>(region , server );
642
+ regionIndexServerIndexRegionCachedRatio .put (regionServerPair , regionCacheRatio );
643
+ }
644
+ if (regionCacheRatio > bestRegionCacheRatio ) {
645
+ serverWithBestRegionCacheRatio = server ;
646
+ // If the server currently hosting the region has equal cache ratio to a historical
647
+ // server, consider the current server to keep hosting the region
648
+ bestRegionCacheRatio = regionCacheRatio ;
649
+ } else if (
650
+ regionCacheRatio == bestRegionCacheRatio && server == regionIndexToServerIndex [region ]
651
+ ) {
652
+ // If two servers have same region cache ratio, then the server currently hosting the
653
+ // region
654
+ // should retain the region
655
+ serverWithBestRegionCacheRatio = server ;
656
+ }
657
+ }
658
+ regionServerIndexWithBestRegionCachedRatio [region ] = serverWithBestRegionCacheRatio ;
659
+ Pair <Integer , Integer > regionServerPair =
660
+ new Pair <>(region , regionIndexToServerIndex [region ]);
661
+ float tempRegionCacheRatio = regionIndexServerIndexRegionCachedRatio .get (regionServerPair );
662
+ if (tempRegionCacheRatio > bestRegionCacheRatio ) {
663
+ LOG .warn (
664
+ "INVALID CONDITION: region {} on server {} cache ratio {} is greater than the "
665
+ + "best region cache ratio {} on server {}" ,
666
+ regions [region ].getEncodedName (), servers [regionIndexToServerIndex [region ]],
667
+ tempRegionCacheRatio , bestRegionCacheRatio , servers [serverWithBestRegionCacheRatio ]);
668
+ }
669
+ }
670
+ }
671
+
672
+ protected float getOrComputeRegionCacheRatio (int region , int server ) {
673
+ if (
674
+ regionServerIndexWithBestRegionCachedRatio == null
675
+ || regionIndexServerIndexRegionCachedRatio .isEmpty ()
676
+ ) {
677
+ computeRegionServerRegionCacheRatio ();
678
+ }
679
+
680
+ Pair <Integer , Integer > regionServerPair = new Pair <>(region , server );
681
+ return regionIndexServerIndexRegionCachedRatio .containsKey (regionServerPair )
682
+ ? regionIndexServerIndexRegionCachedRatio .get (regionServerPair )
683
+ : 0.0f ;
684
+ }
685
+
686
+ public int [] getOrComputeServerWithBestRegionCachedRatio () {
687
+ if (
688
+ regionServerIndexWithBestRegionCachedRatio == null
689
+ || regionIndexServerIndexRegionCachedRatio .isEmpty ()
690
+ ) {
691
+ computeRegionServerRegionCacheRatio ();
692
+ }
693
+ return regionServerIndexWithBestRegionCachedRatio ;
694
+ }
695
+
544
696
/**
545
697
* Maps region index to rack index
546
698
*/
0 commit comments