mirror of
https://github.com/neondatabase/neon.git
synced 2026-06-05 14:30:37 +00:00
pageserver: add max_logical_size_per_shard for get_top_tenants (#11157)
## Problem In #11122, we want to split shards once the logical size of the largest timeline exceeds a split threshold. However, `get_top_tenants` currently only returns `max_logical_size`, which tracks the max _total_ logical size of a timeline across all shards. This is problematic, because the storage controller needs to fetch a list of N tenants that are eligible for splits, but the API doesn't currently have a way to express this. For example, with a split threshold of 1 GB, a tenant with `max_logical_size` of 4 GB is eligible to split if it has 1 or 2 shards, but not if it already has 4 shards. We need to express this in per-shard terms, otherwise the `get_top_tenants` endpoint may end up only returning tenants that can't be split, blocking splits entirely. Touches https://github.com/neondatabase/neon/pull/11122. Touches https://github.com/neondatabase/cloud/issues/22532. ## Summary of changes Add `TenantShardItem::max_logical_size_per_shard` containing `max_logical_size / shard_count`, and `TenantSorting::MaxLogicalSizePerShard` to order and filter by it.
This commit is contained in:
@@ -1476,8 +1476,14 @@ pub struct TenantScanRemoteStorageResponse {
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum TenantSorting {
|
||||
/// Total size of layers on local disk for all timelines in a shard.
|
||||
ResidentSize,
|
||||
/// The logical size of the largest timeline within a _tenant_ (not shard). Only tracked on
|
||||
/// shard 0, contains the sum across all shards.
|
||||
MaxLogicalSize,
|
||||
/// The logical size of the largest timeline within a _tenant_ (not shard), divided by number of
|
||||
/// shards. Only tracked on shard 0, and estimates the per-shard logical size.
|
||||
MaxLogicalSizePerShard,
|
||||
}
|
||||
|
||||
impl Default for TenantSorting {
|
||||
@@ -1507,14 +1513,20 @@ pub struct TopTenantShardsRequest {
|
||||
pub struct TopTenantShardItem {
|
||||
pub id: TenantShardId,
|
||||
|
||||
/// Total size of layers on local disk for all timelines in this tenant
|
||||
/// Total size of layers on local disk for all timelines in this shard.
|
||||
pub resident_size: u64,
|
||||
|
||||
/// Total size of layers in remote storage for all timelines in this tenant
|
||||
/// Total size of layers in remote storage for all timelines in this shard.
|
||||
pub physical_size: u64,
|
||||
|
||||
/// The largest logical size of a timeline within this tenant
|
||||
/// The largest logical size of a timeline within this _tenant_ (not shard). This is only
|
||||
/// tracked on shard 0, and contains the sum of the logical size across all shards.
|
||||
pub max_logical_size: u64,
|
||||
|
||||
/// The largest logical size of a timeline within this _tenant_ (not shard) divided by number of
|
||||
/// shards. This is only tracked on shard 0, and is only an estimate as we divide it evenly by
|
||||
/// shard count, rounded up.
|
||||
pub max_logical_size_per_shard: u64,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default)]
|
||||
|
||||
@@ -3223,6 +3223,7 @@ async fn post_top_tenants(
|
||||
match order_by {
|
||||
TenantSorting::ResidentSize => sizes.resident_size,
|
||||
TenantSorting::MaxLogicalSize => sizes.max_logical_size,
|
||||
TenantSorting::MaxLogicalSizePerShard => sizes.max_logical_size_per_shard,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3842,6 +3842,7 @@ impl Tenant {
|
||||
resident_size: 0,
|
||||
physical_size: 0,
|
||||
max_logical_size: 0,
|
||||
max_logical_size_per_shard: 0,
|
||||
};
|
||||
|
||||
for timeline in self.timelines.lock().unwrap().values() {
|
||||
@@ -3858,6 +3859,10 @@ impl Tenant {
|
||||
);
|
||||
}
|
||||
|
||||
result.max_logical_size_per_shard = result
|
||||
.max_logical_size
|
||||
.div_ceil(self.tenant_shard_id.shard_count.count() as u64);
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user