3434import org .apache .hadoop .hbase .client .RegionReplicaUtil ;
3535import org .apache .hadoop .hbase .master .RackManager ;
3636import org .apache .hadoop .hbase .net .Address ;
37+ import org .apache .hadoop .hbase .util .Pair ;
3738import org .apache .yetus .audience .InterfaceAudience ;
3839import org .slf4j .Logger ;
3940import org .slf4j .LoggerFactory ;
@@ -114,6 +115,12 @@ class BalancerClusterState {
114115 private float [][] rackLocalities ;
115116 // Maps localityType -> region -> [server|rack]Index with highest locality
116117 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 ;
117124
118125 static class DefaultRackManager extends RackManager {
119126 @ Override
@@ -125,13 +132,20 @@ public String getRack(ServerName server) {
125132 BalancerClusterState (Map <ServerName , List <RegionInfo >> clusterState ,
126133 Map <String , Deque <BalancerRegionLoad >> loads , RegionLocationFinder regionFinder ,
127134 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 , RegionLocationFinder regionFinder ,
140+ RackManager rackManager , Map <String , Pair <ServerName , Float >> oldRegionServerRegionCacheRatio ) {
141+ this (null , clusterState , loads , regionFinder , rackManager , oldRegionServerRegionCacheRatio );
129142 }
130143
131144 @ SuppressWarnings ("unchecked" )
132145 BalancerClusterState (Collection <RegionInfo > unassignedRegions ,
133146 Map <ServerName , List <RegionInfo >> clusterState , Map <String , Deque <BalancerRegionLoad >> loads ,
134- RegionLocationFinder regionFinder , RackManager rackManager ) {
147+ RegionLocationFinder regionFinder , RackManager rackManager ,
148+ Map <String , Pair <ServerName , Float >> oldRegionServerRegionCacheRatio ) {
135149 if (unassignedRegions == null ) {
136150 unassignedRegions = Collections .emptyList ();
137151 }
@@ -145,6 +159,8 @@ public String getRack(ServerName server) {
145159 tables = new ArrayList <>();
146160 this .rackManager = rackManager != null ? rackManager : new DefaultRackManager ();
147161
162+ this .regionCacheRatioOnOldServerMap = oldRegionServerRegionCacheRatio ;
163+
148164 numRegions = 0 ;
149165
150166 List <List <Integer >> serversPerHostList = new ArrayList <>();
@@ -527,6 +543,142 @@ private void computeCachedLocalities() {
527543
528544 }
529545
546+ /**
547+ * Returns the size of hFiles from the most recent RegionLoad for region
548+ */
549+ public int getTotalRegionHFileSizeMB (int region ) {
550+ Deque <BalancerRegionLoad > load = regionLoads [region ];
551+ if (load == null ) {
552+ // This means, that the region has no actual data on disk
553+ return 0 ;
554+ }
555+ return regionLoads [region ].getLast ().getRegionSizeMB ();
556+ }
557+
558+ /**
559+ * Returns the weighted cache ratio of a region on the given region server
560+ */
561+ public float getOrComputeWeightedRegionCacheRatio (int region , int server ) {
562+ return getTotalRegionHFileSizeMB (region ) * getOrComputeRegionCacheRatio (region , server );
563+ }
564+
565+ /**
566+ * Returns the amount by which a region is cached on a given region server. If the region is not
567+ * currently hosted on the given region server, then find out if it was previously hosted there
568+ * and return the old cache ratio.
569+ */
570+ protected float getRegionCacheRatioOnRegionServer (int region , int regionServerIndex ) {
571+ float regionCacheRatio = 0.0f ;
572+
573+ // Get the current region cache ratio if the region is hosted on the server regionServerIndex
574+ for (int regionIndex : regionsPerServer [regionServerIndex ]) {
575+ if (region != regionIndex ) {
576+ continue ;
577+ }
578+
579+ Deque <BalancerRegionLoad > regionLoadList = regionLoads [regionIndex ];
580+
581+ // The region is currently hosted on this region server. Get the region cache ratio for this
582+ // region on this server
583+ regionCacheRatio =
584+ regionLoadList == null ? 0.0f : regionLoadList .getLast ().getCurrentRegionCacheRatio ();
585+
586+ return regionCacheRatio ;
587+ }
588+
589+ // Region is not currently hosted on this server. Check if the region was cached on this
590+ // server earlier. This can happen when the server was shutdown and the cache was persisted.
591+ // Search using the region name and server name and not the index id and server id as these ids
592+ // may change when a server is marked as dead or a new server is added.
593+ String regionEncodedName = regions [region ].getEncodedName ();
594+ ServerName serverName = servers [regionServerIndex ];
595+ if (
596+ regionCacheRatioOnOldServerMap != null
597+ && regionCacheRatioOnOldServerMap .containsKey (regionEncodedName )
598+ ) {
599+ Pair <ServerName , Float > cacheRatioOfRegionOnServer =
600+ regionCacheRatioOnOldServerMap .get (regionEncodedName );
601+ if (ServerName .isSameAddress (cacheRatioOfRegionOnServer .getFirst (), serverName )) {
602+ regionCacheRatio = cacheRatioOfRegionOnServer .getSecond ();
603+ if (LOG .isDebugEnabled ()) {
604+ LOG .debug ("Old cache ratio found for region {} on server {}: {}" , regionEncodedName ,
605+ serverName , regionCacheRatio );
606+ }
607+ }
608+ }
609+ return regionCacheRatio ;
610+ }
611+
612+ /**
613+ * Populate the maps containing information about how much a region is cached on a region server.
614+ */
615+ private void computeRegionServerRegionCacheRatio () {
616+ regionIndexServerIndexRegionCachedRatio = new HashMap <>();
617+ regionServerIndexWithBestRegionCachedRatio = new int [numRegions ];
618+
619+ for (int region = 0 ; region < numRegions ; region ++) {
620+ float bestRegionCacheRatio = 0.0f ;
621+ int serverWithBestRegionCacheRatio = 0 ;
622+ for (int server = 0 ; server < numServers ; server ++) {
623+ float regionCacheRatio = getRegionCacheRatioOnRegionServer (region , server );
624+ if (regionCacheRatio > 0.0f || server == regionIndexToServerIndex [region ]) {
625+ // A region with cache ratio 0 on a server means nothing. Hence, just make a note of
626+ // cache ratio only if the cache ratio is greater than 0.
627+ Pair <Integer , Integer > regionServerPair = new Pair <>(region , server );
628+ regionIndexServerIndexRegionCachedRatio .put (regionServerPair , regionCacheRatio );
629+ }
630+ if (regionCacheRatio > bestRegionCacheRatio ) {
631+ serverWithBestRegionCacheRatio = server ;
632+ // If the server currently hosting the region has equal cache ratio to a historical
633+ // server, consider the current server to keep hosting the region
634+ bestRegionCacheRatio = regionCacheRatio ;
635+ } else if (
636+ regionCacheRatio == bestRegionCacheRatio && server == regionIndexToServerIndex [region ]
637+ ) {
638+ // If two servers have same region cache ratio, then the server currently hosting the
639+ // region
640+ // should retain the region
641+ serverWithBestRegionCacheRatio = server ;
642+ }
643+ }
644+ regionServerIndexWithBestRegionCachedRatio [region ] = serverWithBestRegionCacheRatio ;
645+ Pair <Integer , Integer > regionServerPair =
646+ new Pair <>(region , regionIndexToServerIndex [region ]);
647+ float tempRegionCacheRatio = regionIndexServerIndexRegionCachedRatio .get (regionServerPair );
648+ if (tempRegionCacheRatio > bestRegionCacheRatio ) {
649+ LOG .warn (
650+ "INVALID CONDITION: region {} on server {} cache ratio {} is greater than the "
651+ + "best region cache ratio {} on server {}" ,
652+ regions [region ].getEncodedName (), servers [regionIndexToServerIndex [region ]],
653+ tempRegionCacheRatio , bestRegionCacheRatio , servers [serverWithBestRegionCacheRatio ]);
654+ }
655+ }
656+ }
657+
658+ protected float getOrComputeRegionCacheRatio (int region , int server ) {
659+ if (
660+ regionServerIndexWithBestRegionCachedRatio == null
661+ || regionIndexServerIndexRegionCachedRatio .isEmpty ()
662+ ) {
663+ computeRegionServerRegionCacheRatio ();
664+ }
665+
666+ Pair <Integer , Integer > regionServerPair = new Pair <>(region , server );
667+ return regionIndexServerIndexRegionCachedRatio .containsKey (regionServerPair )
668+ ? regionIndexServerIndexRegionCachedRatio .get (regionServerPair )
669+ : 0.0f ;
670+ }
671+
672+ public int [] getOrComputeServerWithBestRegionCachedRatio () {
673+ if (
674+ regionServerIndexWithBestRegionCachedRatio == null
675+ || regionIndexServerIndexRegionCachedRatio .isEmpty ()
676+ ) {
677+ computeRegionServerRegionCacheRatio ();
678+ }
679+ return regionServerIndexWithBestRegionCachedRatio ;
680+ }
681+
530682 /**
531683 * Maps region index to rack index
532684 */
0 commit comments