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

storage controller: don't hold detached tenants in memory #10264

Open
wants to merge 10 commits into
base: main
Choose a base branch
from

Conversation

jcsp
Copy link
Collaborator

@jcsp jcsp commented Jan 3, 2025

Problem

Typical deployments of neon have some tenants that stay in use continuously, and a background churning population of tenants that are created and then fall idle, and are configured to Detached state. Currently, this churn of short lived tenants results in an ever-increasing memory footprint.

Closes: #9712

Summary of changes

  • At startup, filter to only load shards that don't have Detached policy
  • In process_result, check if a tenant's shards are all Detached and observed=={}, and if so drop them from memory
  • In tenant_location_conf and other tenant mutators, load the tenants' shards on-demand if they are not present

@jcsp jcsp added t/feature Issue type: feature, for new features or requests c/storage/controller Component: Storage Controller labels Jan 3, 2025
Copy link

github-actions bot commented Jan 3, 2025

7238 tests run: 6867 passed, 11 failed, 360 skipped (full report)


Failures on Postgres 17

Failures on Postgres 16

Failures on Postgres 15

Failures on Postgres 14

# Run all failed tests locally:
scripts/pytest -vv -n $(nproc) -k "test_tenant_s3_restore[release-pg14] or test_tenant_s3_restore[release-pg14] or test_tenant_s3_restore[release-pg15] or test_tenant_s3_restore[release-pg15] or test_tenant_s3_restore[release-pg16] or test_tenant_s3_restore[release-pg16] or test_tenant_s3_restore[release-pg17] or test_tenant_s3_restore[release-pg17] or test_tenant_s3_restore[release-pg17] or test_tenant_s3_restore[release-pg17] or test_tenant_s3_restore[debug-pg17]"
Flaky tests (3)

Postgres 17

Postgres 14

  • test_physical_replication_config_mismatch_too_many_known_xids: release-arm64

Test coverage report is not available

The comment gets automatically updated with the latest test results
dd47681 at 2025-01-06T19:00:20.682Z :recycle:

@jcsp jcsp marked this pull request as ready for review January 3, 2025 13:06
@jcsp jcsp requested a review from a team as a code owner January 3, 2025 13:06
@jcsp jcsp requested review from arpad-m and VladLazar January 3, 2025 13:06
@@ -330,11 +330,20 @@ impl Persistence {

/// At startup, load the high level state for shards, such as their config + policy. This will
/// be enriched at runtime with state discovered on pageservers.
///
/// We exclude shards configured to be detached. During startup, if we see any attached locations
/// for such shards, they will automatically be detached as 'orphans'.
pub(crate) async fn list_tenant_shards(&self) -> DatabaseResult<Vec<TenantShardPersistence>> {
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: rename to load_active_tenant_shards?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

storage_controller/src/service.rs Show resolved Hide resolved
Comment on lines 1166 to 1168
if tenant.policy == PlacementPolicy::Detached {
self.maybe_drop_tenant(tenant.tenant_shard_id.tenant_id, &mut locked);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a bit scary. Since service state sits behind a sync lock we follow this pattern:

  1. acquire lock and get some in-mem state
  2. do something async
  3. acquire lock again and update something

If step (3) doesn't expect the removal, then we run into trouble. I couldn't find any place with problematic expect or unwrap calls. Generally, this should be pretty safe since we wait on the reconcile spawned by the detach in tenant_location_config and that holds the tenant exclusive lock, but might run into issues if detaches end up taking long.

Copy link
Contributor

Choose a reason for hiding this comment

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

This comment isn't really actionable, but I'm curious about your thoughts on this.

Copy link
Collaborator Author

@jcsp jcsp Jan 6, 2025

Choose a reason for hiding this comment

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

In request handlers, the tenant_op_locks for the tenant should prevent any shenanigans like this.

However, you make an excellent point in this particular context: process_result does not hold that lock. If a request handler took the lock, read the existence of the tenant, and then raced with the processing of a reconciler completion, this could violate the assumption that while holding the lock, a tenant that is in memory should remain in memory.

I think the neatest solution to this is to try and get an exclusive lock around this, and to make our maybe_load and maybe_drop functions take refs to lock handles to prove the callers aren't using them outside the lock, let's try that...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Tightened up the use of op locks in 61bf182

In the process I had the interesting observation that tenant_location_conf holds the lock much longer than it needs to, really it should drop it before waiting for reconcilers, but I don't want to make that change inline here in case it has any spooky side effects.

@jcsp jcsp requested a review from VladLazar January 6, 2025 18:22
@jcsp
Copy link
Collaborator Author

jcsp commented Jan 6, 2025

Let's get this merged and give it a week in staging -- there's a lot of detach/attach churn there, so we should have an excellent chance of spotting any unforseen issues

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c/storage/controller Component: Storage Controller t/feature Issue type: feature, for new features or requests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

storage controller: don't hold detached projects in memory
2 participants