mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
refactoring
This commit is contained in:
parent
19537c9d21
commit
89a62e8007
|
@ -42,11 +42,12 @@ func (c *commandVolumeBalance) Help() string {
|
|||
idealWritableVolumes = totalWritableVolumes / numVolumeServers
|
||||
for hasMovedOneVolume {
|
||||
sort all volume servers ordered by the number of local writable volumes
|
||||
pick the volume server A with the lowest number of writable volumes x
|
||||
pick the volume server B with the highest number of writable volumes y
|
||||
if y > idealWritableVolumes and x +1 <= idealWritableVolumes {
|
||||
if B has a writable volume id v that A does not have {
|
||||
move writable volume v from A to B
|
||||
for any the volume server A with the number of writable volumes x +1 <= idealWritableVolume {
|
||||
if y > idealWritableVolumes and x +1 <= idealWritableVolumes {
|
||||
if B has a writable volume id v that A does not have, and satisfy v replication requirements {
|
||||
move writable volume v from A to B
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -185,7 +186,7 @@ func sortReadOnlyVolumes(volumes []*master_pb.VolumeInformationMessage) {
|
|||
})
|
||||
}
|
||||
|
||||
func balanceSelectedVolume(commandEnv *CommandEnv, nodes []*Node, sortCandidatesFn func(volumes []*master_pb.VolumeInformationMessage), applyBalancing bool) error {
|
||||
func balanceSelectedVolume(commandEnv *CommandEnv, nodes []*Node, sortCandidatesFn func(volumes []*master_pb.VolumeInformationMessage), applyBalancing bool) (err error) {
|
||||
selectedVolumeCount := 0
|
||||
for _, dn := range nodes {
|
||||
selectedVolumeCount += len(dn.selectedVolumes)
|
||||
|
@ -193,48 +194,65 @@ func balanceSelectedVolume(commandEnv *CommandEnv, nodes []*Node, sortCandidates
|
|||
|
||||
idealSelectedVolumes := ceilDivide(selectedVolumeCount, len(nodes))
|
||||
|
||||
hasMove := true
|
||||
hasMoved := true
|
||||
|
||||
for hasMove {
|
||||
hasMove = false
|
||||
for hasMoved {
|
||||
hasMoved = false
|
||||
sort.Slice(nodes, func(i, j int) bool {
|
||||
// TODO sort by free volume slots???
|
||||
return len(nodes[i].selectedVolumes) < len(nodes[j].selectedVolumes)
|
||||
})
|
||||
emptyNode, fullNode := nodes[0], nodes[len(nodes)-1]
|
||||
if len(fullNode.selectedVolumes) > idealSelectedVolumes && len(emptyNode.selectedVolumes)+1 <= idealSelectedVolumes {
|
||||
|
||||
// sort the volumes to move
|
||||
var candidateVolumes []*master_pb.VolumeInformationMessage
|
||||
for _, v := range fullNode.selectedVolumes {
|
||||
candidateVolumes = append(candidateVolumes, v)
|
||||
fullNode := nodes[len(nodes)-1]
|
||||
var candidateVolumes []*master_pb.VolumeInformationMessage
|
||||
for _, v := range fullNode.selectedVolumes {
|
||||
candidateVolumes = append(candidateVolumes, v)
|
||||
}
|
||||
sortCandidatesFn(candidateVolumes)
|
||||
|
||||
for i := 0; i < len(nodes)-1; i++ {
|
||||
emptyNode := nodes[i]
|
||||
if !(len(fullNode.selectedVolumes) > idealSelectedVolumes && len(emptyNode.selectedVolumes)+1 <= idealSelectedVolumes) {
|
||||
// no more volume servers with empty slots
|
||||
break
|
||||
}
|
||||
sortCandidatesFn(candidateVolumes)
|
||||
|
||||
for _, v := range candidateVolumes {
|
||||
if v.ReplicaPlacement > 0 {
|
||||
if fullNode.dc != emptyNode.dc && fullNode.rack != emptyNode.rack {
|
||||
// TODO this logic is too simple, but should work most of the time
|
||||
// Need a correct algorithm to handle all different cases
|
||||
continue
|
||||
}
|
||||
}
|
||||
if _, found := emptyNode.selectedVolumes[v.Id]; !found {
|
||||
if err := moveVolume(commandEnv, v, fullNode, emptyNode, applyBalancing); err == nil {
|
||||
delete(fullNode.selectedVolumes, v.Id)
|
||||
emptyNode.selectedVolumes[v.Id] = v
|
||||
hasMove = true
|
||||
break
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
hasMoved, err = attemptToMoveOneVolume(commandEnv, fullNode, candidateVolumes, emptyNode, applyBalancing)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if hasMoved {
|
||||
// moved one volume
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func attemptToMoveOneVolume(commandEnv *CommandEnv, fullNode *Node, candidateVolumes []*master_pb.VolumeInformationMessage, emptyNode *Node, applyBalancing bool) (hasMoved bool, err error) {
|
||||
|
||||
for _, v := range candidateVolumes {
|
||||
if v.ReplicaPlacement > 0 {
|
||||
if fullNode.dc != emptyNode.dc && fullNode.rack != emptyNode.rack {
|
||||
// TODO this logic is too simple, but should work most of the time
|
||||
// Need a correct algorithm to handle all different cases
|
||||
continue
|
||||
}
|
||||
}
|
||||
if _, found := emptyNode.selectedVolumes[v.Id]; !found {
|
||||
if err = moveVolume(commandEnv, v, fullNode, emptyNode, applyBalancing); err == nil {
|
||||
delete(fullNode.selectedVolumes, v.Id)
|
||||
emptyNode.selectedVolumes[v.Id] = v
|
||||
hasMoved = true
|
||||
break
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func moveVolume(commandEnv *CommandEnv, v *master_pb.VolumeInformationMessage, fullNode *Node, emptyNode *Node, applyBalancing bool) error {
|
||||
collectionPrefix := v.Collection + "_"
|
||||
if v.Collection == "" {
|
||||
|
|
Loading…
Reference in a new issue