Design Distributed Sorting Around an Explicit Helper Contract
AnthropicSoftware Engineer · OnsiteLast updated
Design and implement the coordination logic for a distributed range-based sort across multiple worker nodes, specifying the worker helper contract and handling key skew and duplicate values.
Scenario
In a distributed storage system, data is spread across k worker nodes. You are tasked with implementing the coordinator for a globally ordered distributed sort (TeraSort-style). Instead of pulling all data to a single node, the coordinator must rely on an explicit helper contract exposed by each worker to sample, shuffle, and sort data in parallel.
Worker Helper Contract
Each worker implements the following interface:
class WorkerClient:
def sample_keys(self, num_samples: int) -> list[tuple[int, str]]:
"""Returns a uniform random sample of (key, record_id) pairs from local storage."""
pass
def partition_and_send(self, boundaries: list[tuple[int, str]], worker_addresses: list[str]) -> None:
"""Partitions local records using `boundaries` (length k - 1) and transmits
each partition to the corresponding target worker index [0..k-1]."""
pass
def local_sort_and_commit(self) -> int:
"""Sorts all received partitions in local memory/disk and finalizes.
Returns the count of records held locally after sorting."""
pass
Task
Implement the DistributedSortCoordinator class:
class DistributedSortCoordinator:
def __init__(self, workers: list[WorkerClient]):
self.workers = workers
self.k = len(workers)
def compute_boundaries(self, collected_samples: list[tuple[int, str]]) -> list[tuple[int, str]]:
"""Compute k - 1 splitter keys from all gathered samples to divide data into k balanced buckets."""
pass
def run_sort(self, samples_per_worker: int) -> list[int]:
"""Coordinates the full distributed sort workflow.
Returns a list of record counts per worker [worker_0_count, ..., worker_k-1_count]."""
pass
Requirements & Edge Cases
- Total Global Ordering: Worker
imust store only records strictly less than or equal to Workeri + 1's minimum record, determined by the composite tuple(key, record_id). - Duplicate Keys & Skew: Many records may share the exact same
key. Using(key, record_id)ensures unique ordering and prevents partition overload when a single key has high frequency. - Balanced Partitions: With
kpartitions, boundary selection should pick splitters at approximately equal intervals across the sorted sample set. - Constraints:
k >= 1. Ifk == 1, no boundaries are needed (boundaries = []).samples_per_worker >= 1.
Example
# 3 workers, target 2 boundaries (k - 1 = 2)
samples = [
(10, "r1"), (10, "r2"), (10, "r3"),
(20, "r4"), (30, "r5"), (40, "r6")
]
# Sorted samples: [(10, "r1"), (10, "r2"), (10, "r3"), (20, "r4"), (30, "r5"), (40, "r6")]
# Selecting splitters for 3 partitions (indices ~ 2, 4):
boundaries = [(10, "r3"), (30, "r5")]
# Partition 0 gets records (10, "r3") and (30, "r5")
Hints
Hint 1
Sorting composite `(key, record_id)` tuples naturally resolves duplicate key skew by guaranteeing a strict total order.
Hint 2
To find `k - 1` splitters from `N` sorted samples, select elements at indices `i * (N / k)` for `i` from 1 to `k - 1`.
Hint 3
The coordinator execution phase follows a sequential pipeline: collect samples, compute splitters, trigger `partition_and_send` across all workers, and finally trigger `local_sort_and_commit`.
Follow-up questions
- How would you detect and handle a worker failure occurring midway through the `partition_and_send` shuffle phase?
- If sampling reveals severe key skew without unique record IDs, how can workers break up a single popular key across multiple nodes?
- How does network topology (e.g., cross-rack bandwidth constraints) impact the selection and assignment of worker boundaries?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.