[
https://issues.apache.org/jira/browse/HBASE-30405?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
wenhao reassigned HBASE-30405:
------------------------------
Assignee: (was: wenhao)
> [Balancer] `HDFSBlocksDistribution.getTopHosts()` breaks weight ties by
> hostname, causing the current RS to be misranked and occasional zero-gain
> region moves
> --------------------------------------------------------------------------------------------------------------------------------------------------------------
>
> Key: HBASE-30405
> URL: https://issues.apache.org/jira/browse/HBASE-30405
> Project: HBase
> Issue Type: Bug
> Components: Balancer
> Affects Versions: 2.0.0, 2.5.11
> Reporter: wenhao
> Priority: Trivial
>
> h2. Summary
> When multiple hosts hold an equal total weight of a region's HFiles (i.e.
> equal block locality), {{HDFSBlocksDistribution.getTopHosts()}} resolves the
> tie by hostname. The resulting "most local host" ordering is therefore
> arbitrary with respect to locality, and the host currently serving the region
> is frequently not ranked first even though its locality is identical to the
> top host. This contradicts the documented contract of
> {{BalancerClusterState.regionLocations}} ("regionIndex -> list of serverIndex
> sorted by locality") and, through the most-local-entity selection used by
> {{{}LocalityBasedCandidateGenerator{}}}, can make the stochastic balancer
> emit zero-locality-gain move/swap proposals.
> h2. Problem
> {{HDFSBlocksDistribution.getTopHostsWithWeights()}} builds a {{TreeSet}}
> ordered by {{HostAndWeight.WeightComparator}} and returns its
> {{{}descendingSet(){}}}:
> * {{{}WeightComparator.compare(l, r){}}}: primary key is weight (ascending);
> *when weights are equal, the tie is broken by
> {{l.getHost().compareTo(r.getHost())}}* (hostname, ascending).
> * {{descendingSet()}} reverses that order, so the returned list is: weight
> descending, and {*}among equal weights, hostname descending{*}.
> Consequently the first element of {{getTopHosts()}} is the host with the
> maximum block weight; if several hosts share the same maximum weight, the
> first one is simply the lexicographically largest hostname — not the host
> with any locality advantage.
> h2. Root cause
> # {{HDFSBlocksDistribution.java}}
> ** {{WeightComparator}} tie-break: {{return
> l.getHost().compareTo(r.getHost());}}
> ** {{getTopHostsWithWeights()}} returns
> {{{}orderedHosts.descendingSet(){}}}, so equal-weight hosts are ordered by
> hostname {_}descending{_}.
> # {{RegionLocationFinder.getTopBlockLocations(RegionInfo region)}} returns
> the host list in exactly that order.
> # {{BalancerClusterState.registerRegion()}} fills
> {{regionLocations[regionIndex]}} from that list. The field contract says the
> list is "sorted by locality", but under weight ties it is actually sorted by
> hostname.
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)