2021-10-25 19:48:23 +08:00
|
|
|
// Licensed to the LF AI & Data foundation under one
|
|
|
|
// or more contributor license agreements. See the NOTICE file
|
|
|
|
// distributed with this work for additional information
|
|
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
|
|
// to you under the Apache License, Version 2.0 (the
|
|
|
|
// "License"); you may not use this file except in compliance
|
2021-05-25 16:22:02 +08:00
|
|
|
// with the License. You may obtain a copy of the License at
|
|
|
|
//
|
2021-10-25 19:48:23 +08:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2021-05-25 16:22:02 +08:00
|
|
|
//
|
2021-10-25 19:48:23 +08:00
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
2021-06-23 14:28:08 +08:00
|
|
|
|
2021-06-22 10:42:07 +08:00
|
|
|
package datacoord
|
2021-05-25 16:22:02 +08:00
|
|
|
|
|
|
|
import (
|
2023-03-20 10:01:56 +08:00
|
|
|
"context"
|
|
|
|
"math"
|
2021-10-14 15:44:34 +08:00
|
|
|
"sort"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
2021-05-25 16:22:02 +08:00
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
"github.com/samber/lo"
|
2022-01-05 14:08:42 +08:00
|
|
|
"go.uber.org/zap"
|
2023-03-20 10:01:56 +08:00
|
|
|
"go.uber.org/zap/zapcore"
|
2023-09-21 09:45:27 +08:00
|
|
|
|
|
|
|
"github.com/milvus-io/milvus/pkg/log"
|
2021-05-25 16:22:02 +08:00
|
|
|
)
|
|
|
|
|
2021-12-20 19:46:59 +08:00
|
|
|
// RegisterPolicy decides the channels mapping after registering the nodeID
|
2023-11-09 19:00:25 +08:00
|
|
|
// return bufferedUpdates and balanceUpdates
|
2023-11-13 11:16:18 +08:00
|
|
|
type RegisterPolicy func(store ROChannelStore, nodeID int64) (*ChannelOpSet, *ChannelOpSet)
|
2021-05-25 16:22:02 +08:00
|
|
|
|
2021-12-20 19:46:59 +08:00
|
|
|
// EmptyRegister does nothing
|
2023-11-13 11:16:18 +08:00
|
|
|
func EmptyRegister(store ROChannelStore, nodeID int64) (*ChannelOpSet, *ChannelOpSet) {
|
2023-11-09 19:00:25 +08:00
|
|
|
return nil, nil
|
2021-06-09 18:43:50 +08:00
|
|
|
}
|
|
|
|
|
2021-12-20 19:46:59 +08:00
|
|
|
// BufferChannelAssignPolicy assigns buffer channels to new registered node
|
2023-11-13 11:16:18 +08:00
|
|
|
func BufferChannelAssignPolicy(store ROChannelStore, nodeID int64) *ChannelOpSet {
|
2021-10-14 15:44:34 +08:00
|
|
|
info := store.GetBufferChannelInfo()
|
|
|
|
if info == nil || len(info.Channels) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
2021-05-25 16:22:02 +08:00
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet := NewChannelOpSet(
|
2024-04-16 15:57:19 +08:00
|
|
|
NewDeleteOp(bufferID, lo.Values(info.Channels)...),
|
|
|
|
NewAddOp(nodeID, lo.Values(info.Channels)...))
|
2021-10-14 15:44:34 +08:00
|
|
|
return opSet
|
2021-06-23 14:28:08 +08:00
|
|
|
}
|
|
|
|
|
2021-12-20 19:46:59 +08:00
|
|
|
// AvgAssignRegisterPolicy assigns channels with average to new registered node
|
2022-06-15 20:50:10 +08:00
|
|
|
// Register will not directly delete the node-channel pair. Channel manager will handle channel release.
|
2023-11-13 11:16:18 +08:00
|
|
|
func AvgAssignRegisterPolicy(store ROChannelStore, nodeID int64) (*ChannelOpSet, *ChannelOpSet) {
|
2021-10-26 19:40:44 +08:00
|
|
|
opSet := BufferChannelAssignPolicy(store, nodeID)
|
2023-11-13 11:16:18 +08:00
|
|
|
if opSet != nil {
|
2023-11-09 19:00:25 +08:00
|
|
|
return opSet, nil
|
2021-10-26 19:40:44 +08:00
|
|
|
}
|
|
|
|
|
2022-06-15 20:50:10 +08:00
|
|
|
// Get a list of available node-channel info.
|
2022-10-31 11:35:34 +08:00
|
|
|
avaNodes := filterNode(store.GetNodesChannels(), nodeID)
|
2021-10-26 19:40:44 +08:00
|
|
|
|
|
|
|
channelNum := 0
|
2022-10-31 11:35:34 +08:00
|
|
|
for _, info := range avaNodes {
|
2021-10-26 19:40:44 +08:00
|
|
|
channelNum += len(info.Channels)
|
|
|
|
}
|
2023-02-06 10:33:54 +08:00
|
|
|
// store already add the new node
|
|
|
|
chPerNode := channelNum / len(store.GetNodes())
|
2022-06-15 20:50:10 +08:00
|
|
|
if chPerNode == 0 {
|
2023-11-09 19:00:25 +08:00
|
|
|
return nil, nil
|
2021-10-26 19:40:44 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// sort in descending order and reallocate
|
2022-10-31 11:35:34 +08:00
|
|
|
sort.Slice(avaNodes, func(i, j int) bool {
|
|
|
|
return len(avaNodes[i].Channels) > len(avaNodes[j].Channels)
|
2021-10-26 19:40:44 +08:00
|
|
|
})
|
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
releases := make(map[int64][]RWChannel)
|
2022-06-15 20:50:10 +08:00
|
|
|
for i := 0; i < chPerNode; i++ {
|
|
|
|
// Pick a node with its channel to release.
|
2022-10-31 11:35:34 +08:00
|
|
|
toRelease := avaNodes[i%len(avaNodes)]
|
2022-06-15 20:50:10 +08:00
|
|
|
// Pick a channel that will be reassigned to the new node later.
|
2022-10-31 11:35:34 +08:00
|
|
|
chIdx := i / len(avaNodes)
|
2022-06-15 20:50:10 +08:00
|
|
|
if chIdx >= len(toRelease.Channels) {
|
|
|
|
// Node has too few channels, simply skip. No re-picking.
|
|
|
|
// TODO: Consider re-picking in case assignment is extremely uneven?
|
2021-10-26 19:40:44 +08:00
|
|
|
continue
|
|
|
|
}
|
2024-04-16 15:57:19 +08:00
|
|
|
releases[toRelease.NodeID] = append(releases[toRelease.NodeID], lo.Values(toRelease.Channels)[chIdx])
|
2021-10-26 19:40:44 +08:00
|
|
|
}
|
|
|
|
|
2022-06-15 20:50:10 +08:00
|
|
|
// Channels in `releases` are reassigned eventually by channel manager.
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet = NewChannelOpSet()
|
2022-06-02 13:56:04 +08:00
|
|
|
for k, v := range releases {
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet.Add(k, v...)
|
2021-10-26 19:40:44 +08:00
|
|
|
}
|
2023-11-09 19:00:25 +08:00
|
|
|
return nil, opSet
|
2021-10-26 19:40:44 +08:00
|
|
|
}
|
|
|
|
|
2022-06-15 20:50:10 +08:00
|
|
|
// filterNode filters out node-channel info where node ID == `nodeID`.
|
2021-10-26 19:40:44 +08:00
|
|
|
func filterNode(infos []*NodeChannelInfo, nodeID int64) []*NodeChannelInfo {
|
|
|
|
filtered := make([]*NodeChannelInfo, 0)
|
|
|
|
for _, info := range infos {
|
|
|
|
if info.NodeID == nodeID {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
filtered = append(filtered, info)
|
|
|
|
}
|
|
|
|
return filtered
|
|
|
|
}
|
|
|
|
|
2021-10-14 15:44:34 +08:00
|
|
|
func formatNodeID(nodeID int64) string {
|
|
|
|
return strconv.FormatInt(nodeID, 10)
|
|
|
|
}
|
2021-05-25 16:22:02 +08:00
|
|
|
|
2021-10-14 15:44:34 +08:00
|
|
|
func deformatNodeID(node string) (int64, error) {
|
|
|
|
return strconv.ParseInt(node, 10, 64)
|
2021-05-25 16:22:02 +08:00
|
|
|
}
|
|
|
|
|
2021-10-14 15:44:34 +08:00
|
|
|
// ChannelAssignPolicy assign channels to registered nodes.
|
2023-11-13 11:16:18 +08:00
|
|
|
type ChannelAssignPolicy func(store ROChannelStore, channels []RWChannel) *ChannelOpSet
|
2021-10-14 15:44:34 +08:00
|
|
|
|
|
|
|
// AverageAssignPolicy ensure that the number of channels per nodes is approximately the same
|
2023-11-13 11:16:18 +08:00
|
|
|
func AverageAssignPolicy(store ROChannelStore, channels []RWChannel) *ChannelOpSet {
|
2022-10-31 11:35:34 +08:00
|
|
|
newChannels := filterChannels(store, channels)
|
|
|
|
if len(newChannels) == 0 {
|
2021-10-14 15:44:34 +08:00
|
|
|
return nil
|
2021-05-27 14:14:05 +08:00
|
|
|
}
|
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet := NewChannelOpSet()
|
2022-10-31 11:35:34 +08:00
|
|
|
allDataNodes := store.GetNodesChannels()
|
2021-07-12 11:03:52 +08:00
|
|
|
|
2021-10-14 15:44:34 +08:00
|
|
|
// If no datanode alive, save channels in buffer
|
2022-10-31 11:35:34 +08:00
|
|
|
if len(allDataNodes) == 0 {
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet.Add(bufferID, channels...)
|
2021-10-14 15:44:34 +08:00
|
|
|
return opSet
|
|
|
|
}
|
|
|
|
|
|
|
|
// sort and assign
|
2022-10-31 11:35:34 +08:00
|
|
|
sort.Slice(allDataNodes, func(i, j int) bool {
|
|
|
|
return len(allDataNodes[i].Channels) <= len(allDataNodes[j].Channels)
|
2021-10-14 15:44:34 +08:00
|
|
|
})
|
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
updates := make(map[int64][]RWChannel)
|
2022-10-31 11:35:34 +08:00
|
|
|
for i, newChannel := range newChannels {
|
|
|
|
n := allDataNodes[i%len(allDataNodes)].NodeID
|
|
|
|
updates[n] = append(updates[n], newChannel)
|
2021-10-14 15:44:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for id, chs := range updates {
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet.Add(id, chs...)
|
2021-10-14 15:44:34 +08:00
|
|
|
}
|
|
|
|
return opSet
|
|
|
|
}
|
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
func filterChannels(store ROChannelStore, channels []RWChannel) []RWChannel {
|
|
|
|
channelsMap := make(map[string]RWChannel)
|
2021-10-14 15:44:34 +08:00
|
|
|
for _, c := range channels {
|
2023-11-13 11:16:18 +08:00
|
|
|
channelsMap[c.GetName()] = c
|
2021-10-14 15:44:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
allChannelsInfo := store.GetChannels()
|
|
|
|
for _, info := range allChannelsInfo {
|
|
|
|
for _, c := range info.Channels {
|
2023-11-13 11:16:18 +08:00
|
|
|
delete(channelsMap, c.GetName())
|
2021-05-28 16:48:31 +08:00
|
|
|
}
|
2021-05-27 14:14:05 +08:00
|
|
|
}
|
2021-10-14 15:44:34 +08:00
|
|
|
|
|
|
|
if len(channelsMap) == 0 {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
filtered := make([]RWChannel, 0, len(channelsMap))
|
2021-10-14 15:44:34 +08:00
|
|
|
for _, v := range channelsMap {
|
|
|
|
filtered = append(filtered, v)
|
|
|
|
}
|
|
|
|
return filtered
|
2021-05-27 14:14:05 +08:00
|
|
|
}
|
|
|
|
|
2021-10-14 15:44:34 +08:00
|
|
|
// DeregisterPolicy determine the mapping after deregistering the nodeID
|
2023-11-13 11:16:18 +08:00
|
|
|
type DeregisterPolicy func(store ROChannelStore, nodeID int64) *ChannelOpSet
|
2021-10-14 15:44:34 +08:00
|
|
|
|
|
|
|
// EmptyDeregisterPolicy do nothing
|
2023-11-13 11:16:18 +08:00
|
|
|
func EmptyDeregisterPolicy(store ROChannelStore, nodeID int64) *ChannelOpSet {
|
2021-10-14 15:44:34 +08:00
|
|
|
return nil
|
2021-06-23 14:28:08 +08:00
|
|
|
}
|
|
|
|
|
2021-10-14 15:44:34 +08:00
|
|
|
// AvgAssignUnregisteredChannels evenly assign the unregistered channels
|
2023-11-13 11:16:18 +08:00
|
|
|
func AvgAssignUnregisteredChannels(store ROChannelStore, nodeID int64) *ChannelOpSet {
|
2022-10-31 11:35:34 +08:00
|
|
|
allNodes := store.GetNodesChannels()
|
|
|
|
avaNodes := make([]*NodeChannelInfo, 0, len(allNodes))
|
2023-11-13 11:16:18 +08:00
|
|
|
unregisteredChannels := make([]RWChannel, 0)
|
|
|
|
opSet := NewChannelOpSet()
|
2021-10-14 15:44:34 +08:00
|
|
|
|
2022-10-31 11:35:34 +08:00
|
|
|
for _, c := range allNodes {
|
2021-10-14 15:44:34 +08:00
|
|
|
if c.NodeID == nodeID {
|
2024-04-16 15:57:19 +08:00
|
|
|
opSet.Delete(nodeID, lo.Values(c.Channels)...)
|
|
|
|
unregisteredChannels = append(unregisteredChannels, lo.Values(c.Channels)...)
|
2021-10-14 15:44:34 +08:00
|
|
|
continue
|
|
|
|
}
|
2022-10-31 11:35:34 +08:00
|
|
|
avaNodes = append(avaNodes, c)
|
2021-10-14 15:44:34 +08:00
|
|
|
}
|
|
|
|
|
2022-10-31 11:35:34 +08:00
|
|
|
if len(avaNodes) == 0 {
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet.Add(bufferID, unregisteredChannels...)
|
2021-10-14 15:44:34 +08:00
|
|
|
return opSet
|
|
|
|
}
|
|
|
|
|
|
|
|
// sort and assign
|
2022-10-31 11:35:34 +08:00
|
|
|
sort.Slice(avaNodes, func(i, j int) bool {
|
|
|
|
return len(avaNodes[i].Channels) <= len(avaNodes[j].Channels)
|
2021-10-14 15:44:34 +08:00
|
|
|
})
|
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
updates := make(map[int64][]RWChannel)
|
2022-10-31 11:35:34 +08:00
|
|
|
for i, unregisteredChannel := range unregisteredChannels {
|
|
|
|
n := avaNodes[i%len(avaNodes)].NodeID
|
|
|
|
updates[n] = append(updates[n], unregisteredChannel)
|
2021-10-14 15:44:34 +08:00
|
|
|
}
|
2021-05-25 16:22:02 +08:00
|
|
|
|
2021-10-14 15:44:34 +08:00
|
|
|
for id, chs := range updates {
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet.Add(id, chs...)
|
2021-06-08 19:25:37 +08:00
|
|
|
}
|
2021-10-14 15:44:34 +08:00
|
|
|
return opSet
|
|
|
|
}
|
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
type BalanceChannelPolicy func(store ROChannelStore, ts time.Time) *ChannelOpSet
|
2023-03-20 10:01:56 +08:00
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
func AvgBalanceChannelPolicy(store ROChannelStore, ts time.Time) *ChannelOpSet {
|
|
|
|
opSet := NewChannelOpSet()
|
2023-03-20 10:01:56 +08:00
|
|
|
reAllocates, err := BgBalanceCheck(store.GetNodesChannels(), ts)
|
|
|
|
if err != nil {
|
|
|
|
log.Error("failed to balance node channels", zap.Error(err))
|
2023-11-13 11:16:18 +08:00
|
|
|
return opSet
|
2023-03-20 10:01:56 +08:00
|
|
|
}
|
|
|
|
for _, reAlloc := range reAllocates {
|
2024-04-16 15:57:19 +08:00
|
|
|
opSet.Add(reAlloc.NodeID, lo.Values(reAlloc.Channels)...)
|
2023-03-20 10:01:56 +08:00
|
|
|
}
|
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
return opSet
|
2023-03-20 10:01:56 +08:00
|
|
|
}
|
|
|
|
|
2021-11-16 13:21:16 +08:00
|
|
|
// ChannelReassignPolicy is a policy for reassigning channels
|
2023-11-13 11:16:18 +08:00
|
|
|
type ChannelReassignPolicy func(store ROChannelStore, reassigns []*NodeChannelInfo) *ChannelOpSet
|
2021-10-14 15:44:34 +08:00
|
|
|
|
2021-11-16 13:21:16 +08:00
|
|
|
// EmptyReassignPolicy is a dummy reassign policy
|
2023-11-13 11:16:18 +08:00
|
|
|
func EmptyReassignPolicy(store ROChannelStore, reassigns []*NodeChannelInfo) *ChannelOpSet {
|
2021-10-14 15:44:34 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-03-20 10:01:56 +08:00
|
|
|
// EmptyBalancePolicy is a dummy balance policy
|
2023-11-13 11:16:18 +08:00
|
|
|
func EmptyBalancePolicy(store ROChannelStore, ts time.Time) *ChannelOpSet {
|
2023-03-20 10:01:56 +08:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// AverageReassignPolicy is a reassigning policy that evenly balance channels among datanodes
|
|
|
|
// which is used by bgChecker
|
2023-11-13 11:16:18 +08:00
|
|
|
func AverageReassignPolicy(store ROChannelStore, reassigns []*NodeChannelInfo) *ChannelOpSet {
|
2023-03-20 10:01:56 +08:00
|
|
|
allNodes := store.GetNodesChannels()
|
|
|
|
filterMap := make(map[int64]struct{})
|
|
|
|
toReassignTotalNum := 0
|
|
|
|
for _, reassign := range reassigns {
|
|
|
|
filterMap[reassign.NodeID] = struct{}{}
|
|
|
|
toReassignTotalNum += len(reassign.Channels)
|
|
|
|
}
|
|
|
|
avaNodes := make([]*NodeChannelInfo, 0, len(allNodes))
|
|
|
|
avaNodesChannelSum := 0
|
|
|
|
for _, node := range allNodes {
|
|
|
|
if _, ok := filterMap[node.NodeID]; ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
avaNodes = append(avaNodes, node)
|
|
|
|
avaNodesChannelSum += len(node.Channels)
|
|
|
|
}
|
|
|
|
log.Info("AverageReassignPolicy working", zap.Int("avaNodesCount", len(avaNodes)),
|
|
|
|
zap.Int("toAssignChannelNum", toReassignTotalNum), zap.Int("avaNodesChannelSum", avaNodesChannelSum))
|
2023-11-13 11:16:18 +08:00
|
|
|
|
2023-03-20 10:01:56 +08:00
|
|
|
if len(avaNodes) == 0 {
|
|
|
|
// if no node is left, do not reassign
|
|
|
|
log.Warn("there is no available nodes when reassigning, return")
|
2023-11-13 11:16:18 +08:00
|
|
|
return nil
|
2023-03-20 10:01:56 +08:00
|
|
|
}
|
|
|
|
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet := NewChannelOpSet()
|
2023-03-20 10:01:56 +08:00
|
|
|
avgChannelCount := int(math.Ceil(float64(avaNodesChannelSum+toReassignTotalNum) / (float64(len(avaNodes)))))
|
|
|
|
sort.Slice(avaNodes, func(i, j int) bool {
|
|
|
|
if len(avaNodes[i].Channels) == len(avaNodes[j].Channels) {
|
|
|
|
return avaNodes[i].NodeID < avaNodes[j].NodeID
|
|
|
|
}
|
|
|
|
return len(avaNodes[i].Channels) < len(avaNodes[j].Channels)
|
|
|
|
})
|
|
|
|
|
|
|
|
// reassign channels to remaining nodes
|
|
|
|
addUpdates := make(map[int64]*ChannelOp)
|
|
|
|
for _, reassign := range reassigns {
|
2024-04-16 15:57:19 +08:00
|
|
|
opSet.Delete(reassign.NodeID, lo.Values(reassign.Channels)...)
|
2023-03-20 10:01:56 +08:00
|
|
|
for _, ch := range reassign.Channels {
|
|
|
|
nodeIdx := 0
|
|
|
|
for {
|
|
|
|
targetID := avaNodes[nodeIdx%len(avaNodes)].NodeID
|
|
|
|
if nodeIdx < len(avaNodes) {
|
|
|
|
existedChannelCount := store.GetNodeChannelCount(targetID)
|
|
|
|
if _, ok := addUpdates[targetID]; !ok {
|
|
|
|
if existedChannelCount >= avgChannelCount {
|
|
|
|
log.Debug("targetNodeID has had more channels than average, skip", zap.Int64("targetID",
|
|
|
|
targetID), zap.Int("existedChannelCount", existedChannelCount))
|
|
|
|
nodeIdx++
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
addingChannelCount := len(addUpdates[targetID].Channels)
|
|
|
|
if existedChannelCount+addingChannelCount >= avgChannelCount {
|
|
|
|
log.Debug("targetNodeID has had more channels than average, skip", zap.Int64("targetID",
|
|
|
|
targetID), zap.Int("currentChannelCount", existedChannelCount+addingChannelCount))
|
|
|
|
nodeIdx++
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
nodeIdx++
|
|
|
|
}
|
|
|
|
if _, ok := addUpdates[targetID]; !ok {
|
2023-11-13 11:16:18 +08:00
|
|
|
addUpdates[targetID] = NewAddOp(targetID, ch)
|
2023-03-20 10:01:56 +08:00
|
|
|
} else {
|
2023-11-13 11:16:18 +08:00
|
|
|
addUpdates[targetID].Append(ch)
|
2023-03-20 10:01:56 +08:00
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-11-13 11:16:18 +08:00
|
|
|
opSet.Insert(lo.Values(addUpdates)...)
|
|
|
|
return opSet
|
2023-03-20 10:01:56 +08:00
|
|
|
}
|
|
|
|
|
2021-10-14 15:44:34 +08:00
|
|
|
// ChannelBGChecker check nodes' channels and return the channels needed to be reallocated.
|
2023-03-20 10:01:56 +08:00
|
|
|
type ChannelBGChecker func(ctx context.Context)
|
2021-10-14 15:44:34 +08:00
|
|
|
|
2021-11-19 18:05:25 +08:00
|
|
|
// EmptyBgChecker does nothing
|
2021-10-14 15:44:34 +08:00
|
|
|
func EmptyBgChecker(channels []*NodeChannelInfo, ts time.Time) ([]*NodeChannelInfo, error) {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
2023-03-20 10:01:56 +08:00
|
|
|
type ReAllocates []*NodeChannelInfo
|
|
|
|
|
|
|
|
func (rallocates ReAllocates) MarshalLogArray(enc zapcore.ArrayEncoder) error {
|
|
|
|
for _, nChannelInfo := range rallocates {
|
|
|
|
enc.AppendString("nodeID:")
|
|
|
|
enc.AppendInt64(nChannelInfo.NodeID)
|
|
|
|
cstr := "["
|
|
|
|
if len(nChannelInfo.Channels) > 0 {
|
|
|
|
for _, s := range nChannelInfo.Channels {
|
2023-11-13 11:16:18 +08:00
|
|
|
cstr += s.GetName()
|
2023-03-20 10:01:56 +08:00
|
|
|
cstr += ", "
|
2021-10-14 15:44:34 +08:00
|
|
|
}
|
2023-03-20 10:01:56 +08:00
|
|
|
cstr = cstr[:len(cstr)-2]
|
2021-10-14 15:44:34 +08:00
|
|
|
}
|
2023-03-20 10:01:56 +08:00
|
|
|
cstr += "]"
|
|
|
|
enc.AppendString(cstr)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func BgBalanceCheck(nodeChannels []*NodeChannelInfo, ts time.Time) ([]*NodeChannelInfo, error) {
|
|
|
|
avaNodeNum := len(nodeChannels)
|
|
|
|
reAllocations := make(ReAllocates, 0, avaNodeNum)
|
|
|
|
if avaNodeNum == 0 {
|
2021-12-17 19:46:42 +08:00
|
|
|
return reAllocations, nil
|
2021-10-14 15:44:34 +08:00
|
|
|
}
|
2023-03-20 10:01:56 +08:00
|
|
|
totalChannelNum := 0
|
|
|
|
for _, nodeChs := range nodeChannels {
|
|
|
|
totalChannelNum += len(nodeChs.Channels)
|
|
|
|
}
|
|
|
|
channelCountPerNode := totalChannelNum / avaNodeNum
|
|
|
|
for _, nChannels := range nodeChannels {
|
|
|
|
chCount := len(nChannels.Channels)
|
|
|
|
if chCount <= channelCountPerNode+1 {
|
|
|
|
log.Info("node channel count is not much larger than average, skip reallocate",
|
|
|
|
zap.Int64("nodeID", nChannels.NodeID), zap.Int("channelCount", chCount),
|
|
|
|
zap.Int("channelCountPerNode", channelCountPerNode))
|
|
|
|
continue
|
|
|
|
}
|
2024-04-16 15:57:19 +08:00
|
|
|
reallocate := NewNodeChannelInfo(nChannels.NodeID)
|
2023-03-20 10:01:56 +08:00
|
|
|
toReleaseCount := chCount - channelCountPerNode - 1
|
|
|
|
for _, ch := range nChannels.Channels {
|
2024-04-16 15:57:19 +08:00
|
|
|
reallocate.AddChannel(ch)
|
2023-03-20 10:01:56 +08:00
|
|
|
toReleaseCount--
|
|
|
|
if toReleaseCount <= 0 {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
reAllocations = append(reAllocations, reallocate)
|
|
|
|
}
|
|
|
|
log.Info("Channel Balancer got new reAllocations:", zap.Array("reAllocations", reAllocations))
|
|
|
|
return reAllocations, nil
|
2021-10-14 15:44:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func formatNodeIDs(ids []int64) []string {
|
|
|
|
formatted := make([]string, 0, len(ids))
|
|
|
|
for _, id := range ids {
|
|
|
|
formatted = append(formatted, formatNodeID(id))
|
|
|
|
}
|
|
|
|
return formatted
|
|
|
|
}
|
|
|
|
|
|
|
|
func formatNodeIDsWithFilter(ids []int64, filter int64) []string {
|
|
|
|
formatted := make([]string, 0, len(ids))
|
|
|
|
for _, id := range ids {
|
|
|
|
if id == filter {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
formatted = append(formatted, formatNodeID(id))
|
|
|
|
}
|
|
|
|
return formatted
|
2021-06-23 14:28:08 +08:00
|
|
|
}
|