mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-11 00:37:52 +02:00
balance: share replica-placement logic between shell and worker (#10169)
The replica-placement rule (data-center/rack/same-node limits plus host anti-affinity) existed three times: the shell's satisfyReplicaPlacement/isGoodMove used by volume.balance, fix.replication, and tier.move, and a line-for-line port in the maintenance balance worker. Move the canonical logic into weed/topology/balancer on a shared Location type; the shell and worker keep thin adapters that convert their own location representation and call it. Behavior is unchanged (the shared IsGoodMove keeps the shell's reject-move-to-self guard, and all four replica test suites pass).
This commit is contained in:
1 parent
bea1357d38
commit
d02ee6d5df
5 files changed
+261
-271
No files matched your search
@@ -659,43 +659,29 @@ func moveVolume(commandEnv *CommandEnv, v *master_pb.VolumeInformationMessage, f
|
||||
return nil
|
||||
}
|
||||
|
||||
// toBalancerLocation converts a shell replica location to the shared placement
|
||||
// abstraction, resolving the physical host for machine anti-affinity.
|
||||
func toBalancerLocation(loc *location) balancer.Location {
|
||||
return balancer.Location{
|
||||
DataCenter: loc.dc,
|
||||
Rack: loc.rack,
|
||||
NodeID: loc.dataNode.Id,
|
||||
Host: pb.NewServerAddressFromDataNode(loc.dataNode).ToHost(),
|
||||
}
|
||||
}
|
||||
|
||||
func isGoodMove(placement *super_block.ReplicaPlacement, existingReplicas []*VolumeReplica, sourceNode, targetNode *Node) bool {
|
||||
for _, replica := range existingReplicas {
|
||||
if replica.location.dataNode.Id == targetNode.info.Id &&
|
||||
replica.location.rack == targetNode.rack &&
|
||||
replica.location.dc == targetNode.dc {
|
||||
// never move to existing nodes
|
||||
return false
|
||||
}
|
||||
locs := make([]balancer.Location, len(existingReplicas))
|
||||
for i, replica := range existingReplicas {
|
||||
locs[i] = toBalancerLocation(replica.location)
|
||||
}
|
||||
|
||||
// existing replicas except the one on sourceNode
|
||||
existingReplicasExceptSourceNode := make([]*VolumeReplica, 0)
|
||||
for _, replica := range existingReplicas {
|
||||
if replica.location.dataNode.Id != sourceNode.info.Id {
|
||||
existingReplicasExceptSourceNode = append(existingReplicasExceptSourceNode, replica)
|
||||
}
|
||||
target := balancer.Location{
|
||||
DataCenter: targetNode.dc,
|
||||
Rack: targetNode.rack,
|
||||
NodeID: targetNode.info.Id,
|
||||
Host: pb.NewServerAddressFromDataNode(targetNode.info).ToHost(),
|
||||
}
|
||||
|
||||
// Don't move a replica onto a machine (host) that already holds one of this
|
||||
// volume's replicas: servers sharing a host are one fault domain, so both would
|
||||
// die together. Best-effort -- skip and let balancing try the next target.
|
||||
targetHost := pb.NewServerAddressFromDataNode(targetNode.info).ToHost()
|
||||
for _, replica := range existingReplicasExceptSourceNode {
|
||||
if pb.NewServerAddressFromDataNode(replica.location.dataNode).ToHost() == targetHost {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// target location
|
||||
targetLocation := location{
|
||||
dc: targetNode.dc,
|
||||
rack: targetNode.rack,
|
||||
dataNode: targetNode.info,
|
||||
}
|
||||
|
||||
// check if this satisfies replication requirements
|
||||
return satisfyReplicaPlacement(placement, existingReplicasExceptSourceNode, targetLocation)
|
||||
return balancer.IsGoodMove(placement, locs, sourceNode.info.Id, target)
|
||||
}
|
||||
|
||||
// addDiskFreeBytes adjusts a disk's reported free bytes by delta (negative when a
|
||||
|
||||
Reference in new issue
Block a user