Skip to content
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

flow based tablet load balancer #16351

Merged
merged 14 commits into from
Aug 29, 2024
Merged

Conversation

demmer
Copy link
Member

@demmer demmer commented Jul 8, 2024

Description

Implement an optional flow-based tablet balancer.

The motivation and algorithm is described more in #12241 and in a long comment in the code.

In brief, the goal of this implementation is to more evenly balance out the queries to a the replicas in a shard when the tablets are not evenly distributed across the various cells where vtgates are receiving application traffic, because the default routing algorithm will always prefer an available tablet in the same cell as the vtgate, even if there are more idle tablets in other cells. The balancer addresses this by attempting to route an equal share to each tablet, preferring the same-cell where possible, but crossing cells in order to achieve better global balance.

Slack production results

Note that the original algorithm was developed many months ago, but only recently have we made the time to deploy this within Slack and spent some time to verify it works as expected.

The results from our initial testing are very encouraging and we have been running with this feature enabled for some time now on one of our main production keyspaces. This is a 16 shard keyspace with between 9-11 tablets per shard spread among our 4 active cells. Each cell receives the same amount of inbound traffic.

When we first enabled the feature shows that the wide disparity in QPS per replica goes away and instead the QPS is only based on the number of replicas per shard, as expected:
image

Since then we have actually normalized our deployment so each shard has 9 replicas and the QPS is quite even across all hosts, even though again they do not map evenly to each cell:
image

Related Issue(s)

#12241

Checklist

  • "Backport to:" labels have been added if this change should be back-ported to release branches
  • If this change is to be back-ported to previous releases, a justification is included in the PR description
  • Tests were added or are not required
  • Did the new or modified tests pass consistently locally and on CI?
  • Documentation was added or is not required Tabletbalancer docs website#1804

Deployment Notes

demmer and others added 2 commits July 8, 2024 14:40
Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
Co-authored-by: Venkatraju V <venkatraju@slack-corp.com>
Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
Co-authored-by: Venkatraju V <venkatraju@slack-corp.com>
Copy link
Contributor

vitess-bot bot commented Jul 8, 2024

Review Checklist

Hello reviewers! 👋 Please follow this checklist when reviewing this Pull Request.

General

  • Ensure that the Pull Request has a descriptive title.
  • Ensure there is a link to an issue (except for internal cleanup and flaky test fixes), new features should have an RFC that documents use cases and test cases.

Tests

  • Bug fixes should have at least one unit or end-to-end test, enhancement and new features should have a sufficient number of tests.

Documentation

  • Apply the release notes (needs details) label if users need to know about this change.
  • New features should be documented.
  • There should be some code comments as to why things are implemented the way they are.
  • There should be a comment at the top of each new or modified test to explain what the test does.

New flags

  • Is this flag really necessary?
  • Flag names must be clear and intuitive, use dashes (-), and have a clear help text.

If a workflow is added or modified:

  • Each item in Jobs should be named in order to mark it as required.
  • If the workflow needs to be marked as required, the maintainer team must be notified.

Backward compatibility

  • Protobuf changes should be wire-compatible.
  • Changes to _vt tables and RPCs need to be backward compatible.
  • RPC changes should be compatible with vitess-operator
  • If a flag is removed, then it should also be removed from vitess-operator and arewefastyet, if used there.
  • vtctl command output order should be stable and awk-able.

@vitess-bot vitess-bot bot added NeedsBackportReason If backport labels have been applied to a PR, a justification is required NeedsDescriptionUpdate The description is not clear or comprehensive enough, and needs work NeedsIssue A linked issue is missing for this Pull Request NeedsWebsiteDocsUpdate What it says labels Jul 8, 2024
@github-actions github-actions bot added this to the v21.0.0 milestone Jul 8, 2024
Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
Copy link

codecov bot commented Jul 8, 2024

Codecov Report

Attention: Patch coverage is 83.22148% with 25 lines in your changes missing coverage. Please review.

Project coverage is 68.93%. Comparing base (feb845a) to head (707d77b).
Report is 34 commits behind head on main.

Files with missing lines Patch % Lines
go/vt/vtgate/tabletgateway.go 64.51% 11 Missing ⚠️
go/vt/vtgate/balancer/balancer.go 92.03% 9 Missing ⚠️
go/vt/vtgate/vtgate.go 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #16351      +/-   ##
==========================================
- Coverage   68.98%   68.93%   -0.05%     
==========================================
  Files        1562     1565       +3     
  Lines      200697   201473     +776     
==========================================
+ Hits       138446   138886     +440     
- Misses      62251    62587     +336     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@systay systay added Type: Enhancement Logical improvement (somewhere between a bug and feature) Component: Query Serving and removed NeedsDescriptionUpdate The description is not clear or comprehensive enough, and needs work NeedsIssue A linked issue is missing for this Pull Request NeedsBackportReason If backport labels have been applied to a PR, a justification is required labels Jul 9, 2024
@systay
Copy link
Collaborator

systay commented Jul 9, 2024

This looks great @demmer

Just need to use rand/v2 to make CI happy, and then we need a website PR for the new flags, right?

venkatraju and others added 2 commits July 9, 2024 09:13
Signed-off-by: Venkatraju V <venkatraju@slack-corp.com>
Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
@demmer
Copy link
Member Author

demmer commented Jul 10, 2024

@systay based on the test coverage reports, @venkatraju and I added some more tests for the balancer, and I beefed up some of the existing tests for the retry logic, including running both with and without the balancer. might be overkill but this is kinda a critical part of the code :)

go/vt/vtgate/tabletgateway.go Outdated Show resolved Hide resolved
go/vt/vtgate/tabletgateway.go Outdated Show resolved Hide resolved
@@ -62,6 +70,9 @@ func init() {
fs.StringVar(&CellsToWatch, "cells_to_watch", "", "comma-separated list of cells for watching tablets")
fs.DurationVar(&initialTabletTimeout, "gateway_initial_tablet_timeout", 30*time.Second, "At startup, the tabletGateway will wait up to this duration to get at least one tablet per keyspace/shard/tablet type")
fs.IntVar(&retryCount, "retry-count", 2, "retry count")
fs.BoolVar(&balancerEnabled, "balancer_enabled", false, "Whether to enable the tablet balancer to evenly spread query load")
fs.StringSliceVar(&balancerVtgateCells, "balancer_vtgate_cells", []string{}, "When in balanced mode, a comma-separated list of cells that contain vtgates (required)")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fs.StringSliceVar(&balancerVtgateCells, "balancer_vtgate_cells", []string{}, "When in balanced mode, a comma-separated list of cells that contain vtgates (required)")
fs.StringSliceVar(&balancerVtgateCells, "balancer-vtgate-cells", []string{}, "When in balanced mode, a comma-separated list of cells that contain vtgates (required)")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything else is cosmetic, but this seems important.
What happens if you add vtgates to a cell that didn't previously have any? You would have to restart every vtgate with a new value for this flag?
It may not be very common in practice, but it should be documented somewhere.
Of course, the real answer is that vtgates should be given a list of all cells and discover which ones contain vtgates, but we've so far avoided adding vtgates to the topo.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you add vtgates to a cell that didn't previously have any? You would have to restart every vtgate with a new value for this flag?

Yep. For the current algorithm to work as designed, it's required that all the vtgates know the fully set of cells that are running vtgates and that the load among these cells is roughly even. This allows each individual vtgate to make the assumption about what the others will do without needing signaling.

If you want to change this assumption therefore, you do have to restart the whole fleet to take it into account, just like any other vtgate flag change.

It may not be very common in practice, but it should be documented somewhere.

That makes sense. I'll include something to this effect when we write the website docs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course, the real answer is that vtgates should be given a list of all cells and discover which ones contain vtgates, but we've so far avoided adding vtgates to the topo.

Yeah - that's obviously beyond the scope of this PR, and it would in theory reduce the dependency that query inflows per cell need to be balanced (i.e. you could use the number of gates as a proxy for how much load you expect).

@@ -62,6 +70,9 @@ func init() {
fs.StringVar(&CellsToWatch, "cells_to_watch", "", "comma-separated list of cells for watching tablets")
fs.DurationVar(&initialTabletTimeout, "gateway_initial_tablet_timeout", 30*time.Second, "At startup, the tabletGateway will wait up to this duration to get at least one tablet per keyspace/shard/tablet type")
fs.IntVar(&retryCount, "retry-count", 2, "retry count")
fs.BoolVar(&balancerEnabled, "balancer_enabled", false, "Whether to enable the tablet balancer to evenly spread query load")
fs.StringSliceVar(&balancerVtgateCells, "balancer_vtgate_cells", []string{}, "When in balanced mode, a comma-separated list of cells that contain vtgates (required)")
fs.StringSliceVar(&balancerKeyspaces, "balancer_keyspaces", []string{}, "When in balanced mode, a comma-separated list of keyspaces for which to use the balancer (optional)")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fs.StringSliceVar(&balancerKeyspaces, "balancer_keyspaces", []string{}, "When in balanced mode, a comma-separated list of keyspaces for which to use the balancer (optional)")
fs.StringSliceVar(&balancerKeyspaces, "balancer-keyspaces", []string{}, "When in balanced mode, a comma-separated list of keyspaces for which to use the balancer (optional)")

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious, why was this added? So that you can opt in and out per keyspace as a phased rollout?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep exactly. That's how we did the rollout testing inside Slack -- started with a loadtest keyspace only and then moved to the one production keyspace where we saw the most imbalance, so we could focus on that without worrying about potential negative impact on the rest of the (thousands of) shards.

Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
@deepthi
Copy link
Member

deepthi commented Aug 27, 2024

@venkatraju looks like this may need either a merge from main, or a simpler code change to pass linter checks.

Signed-off-by: Venkatraju V <venkatraju@slack-corp.com>
@venkatraju
Copy link
Contributor

@venkatraju looks like this may need either a merge from main, or a simpler code change to pass linter checks.

@deepthi Fixed the log line that was triggering the linter error.

@deepthi deepthi added the release notes (needs details) This PR needs to be listed in the release notes in a dedicated section (deprecation notice, etc...) label Aug 28, 2024
@deepthi
Copy link
Member

deepthi commented Aug 28, 2024

@systay @rohit-nayak-ps do either of you think this needs a release note?

I've added the label to block merging. This will be a nice thing to add to the release notes.
@venkatraju can you please add a section to the summary release notes doc for this feature? It should go into https://github.com/vitessio/vitess/blob/main/changelog/21.0/21.0.0/summary.md

@venkatraju venkatraju force-pushed the tabletbalancer-v21 branch 2 times, most recently from b2f8253 to 3b889d6 Compare August 29, 2024 00:04
Signed-off-by: Venkatraju V <venkatraju@slack-corp.com>
Signed-off-by: Venkatraju V <venkatraju@slack-corp.com>
Signed-off-by: Venkatraju <venkatraju@gmail.com>
@venkatraju
Copy link
Contributor

@venkatraju can you please add a section to the summary release notes doc for this feature? It should go into https://github.com/vitessio/vitess/blob/main/changelog/21.0/21.0.0/summary.md

@deepthi added release notes. Could you review the text, and also comment on whether you want the new flags called out there?

(sorry about the messed up git history from a rebase that went wrong)

@systay systay removed the release notes (needs details) This PR needs to be listed in the release notes in a dedicated section (deprecation notice, etc...) label Aug 29, 2024
@deepthi
Copy link
Member

deepthi commented Aug 29, 2024

@venkatraju can you please add a section to the summary release notes doc for this feature? It should go into https://github.com/vitessio/vitess/blob/main/changelog/21.0/21.0.0/summary.md

@deepthi added release notes. Could you review the text, and also comment on whether you want the new flags called out there?

(sorry about the messed up git history from a rebase that went wrong)

This looks fine. Details on flags will be in the vtgate command reference (auto generated).

@deepthi deepthi merged commit e799299 into vitessio:main Aug 29, 2024
129 of 130 checks passed
venkatraju added a commit to slackhq/vitess that referenced this pull request Aug 29, 2024
Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
Signed-off-by: Venkatraju V <venkatraju@slack-corp.com>
Signed-off-by: Venkatraju <venkatraju@gmail.com>
Co-authored-by: Venkatraju V <venkatraju@slack-corp.com>
Co-authored-by: Venkatraju <venkatraju@gmail.com>
venkatraju added a commit to slackhq/vitess that referenced this pull request Sep 3, 2024
* flow based tablet load balancer (vitessio#16351)

Signed-off-by: Michael Demmer <mdemmer@slack-corp.com>
Signed-off-by: Venkatraju V <venkatraju@slack-corp.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Query Serving Type: Enhancement Logical improvement (somewhere between a bug and feature)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants