-
Notifications
You must be signed in to change notification settings - Fork 38.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use hash in federated replica set planner #31814
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,6 +17,7 @@ limitations under the License. | |
package planer | ||
|
||
import ( | ||
"hash/fnv" | ||
"math" | ||
"sort" | ||
|
||
|
@@ -31,6 +32,7 @@ type Planner struct { | |
|
||
type namedClusterReplicaSetPreferences struct { | ||
clusterName string | ||
hash uint32 | ||
fed_api.ClusterReplicaSetPreferences | ||
} | ||
|
||
|
@@ -39,9 +41,10 @@ type byWeight []*namedClusterReplicaSetPreferences | |
func (a byWeight) Len() int { return len(a) } | ||
func (a byWeight) Swap(i, j int) { a[i], a[j] = a[j], a[i] } | ||
|
||
// Preferences are sorted according by decreasing weight and increasing clusterName. | ||
// Preferences are sorted according by decreasing weight and increasing hash (built on top of cluster name and rs name). | ||
// Sorting is made by a hash to avoid assigning single-replica rs to the alphabetically smallest cluster. | ||
func (a byWeight) Less(i, j int) bool { | ||
return (a[i].Weight > a[j].Weight) || (a[i].Weight == a[j].Weight && a[i].clusterName < a[j].clusterName) | ||
return (a[i].Weight > a[j].Weight) || (a[i].Weight == a[j].Weight && a[i].hash < a[j].hash) | ||
} | ||
|
||
func NewPlanner(preferences *fed_api.FederatedReplicaSetPreferences) *Planner { | ||
|
@@ -56,21 +59,28 @@ func NewPlanner(preferences *fed_api.FederatedReplicaSetPreferences) *Planner { | |
// have all of the replicas assigned. In such case a cluster with higher weight has priority over | ||
// cluster with lower weight (or with lexicographically smaller name in case of draw). | ||
// It can also use the current replica count and estimated capacity to provide better planning and | ||
// adhere to rebalance policy. | ||
// adhere to rebalance policy. To avoid prioritization of clusters with smaller lexiconographical names | ||
// a semi-random string (like replica set name) can be provided. | ||
// Two maps are returned: | ||
// * a map that contains information how many replicas will be possible to run in a cluster. | ||
// * a map that contains information how many extra replicas would be nice to schedule in a cluster so, | ||
// if by chance, they are scheudled we will be closer to the desired replicas layout. | ||
func (p *Planner) Plan(replicasToDistribute int64, availableClusters []string, currentReplicaCount map[string]int64, | ||
estimatedCapacity map[string]int64) (map[string]int64, map[string]int64) { | ||
estimatedCapacity map[string]int64, replicaSetKey string) (map[string]int64, map[string]int64) { | ||
|
||
preferences := make([]*namedClusterReplicaSetPreferences, 0, len(availableClusters)) | ||
plan := make(map[string]int64, len(preferences)) | ||
overflow := make(map[string]int64, len(preferences)) | ||
|
||
named := func(name string, pref fed_api.ClusterReplicaSetPreferences) *namedClusterReplicaSetPreferences { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it probably should be:
[the name is actually name of a cluster right? And it's completely not clear for here.] |
||
// Seems to work better than addler for our case. | ||
hasher := fnv.New32() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In all places in the codebases we are using adler32 hash, see e.g.: I would like to be consistent and use the same hasing method here too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I made some experiments and adler32 tends to preserve alphabetical order. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand - alphabetical order of what? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added comment. |
||
hasher.Write([]byte(name)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You may consider using this one: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't need a hash over a whole object. Just name+namespace. |
||
hasher.Write([]byte(replicaSetKey)) | ||
|
||
return &namedClusterReplicaSetPreferences{ | ||
clusterName: name, | ||
clusterName: name, | ||
hash: hasher.Sum32(), | ||
ClusterReplicaSetPreferences: pref, | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually - I thought that I understood this change initially, but now I no longer think I understand it.
Please add a comment, why you actually can't compare based on clusterName here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added.