mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #3028] [RFC]: Fixed-Lifecycle Soft Pin with Request-Level TTL and Deadline-Indexed Expiration #777
Labels
No labels
ascend
auto-closed
bug
bug
CI/Build
Common
documentation
enhancement
feature request
good first issue
help wanted
high priority
MetaX
nightly-failure
pull-request
PyTorch Backend
question
RFC
Roadmap
stale
Store
Tests
Transfer Engine
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
kvcache-ai/Mooncake#777
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @Lin-z-w on GitHub (Jul 21, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/3028
Changes proposed
Summary
This RFC proposes changing Mooncake Store soft pinning from an access-renewed lease into a fixed-lifecycle eviction-priority hint.
A soft pin starts when the first replica of a write becomes readable. Its deadline is fixed for that activation and is not extended by
Get,Exist, group lease refresh, replica copy/move, or storage promotion. When the deadline is reached, the object becomes ordinary cache. A later write may explicitly enable soft pinning again.The proposal also adds an optional request-level TTL, an explicit
Preserve | Enable | Disablewrite action, and a deadline index so expiration cleanup processes only due objects instead of scanning all metadata.Related work:
Motivation
The current soft-pin representation retains a
soft_pin_timeoutafter the deadline has passed. Read-lease refresh paths can subsequently move that timeout into the future, causing an expired soft pin to become active again simply because the object was accessed.This behavior creates several problems:
O(total object count)even when few or no soft pins expire.The desired behavior is a predictable priority lifetime suitable for both standalone objects and future group-retention policy.
Proposed semantics
Enable(ttl)sets a deadline relative to that completion time.now >= deadline, the object is treated as ordinary cache.Enablemay start a new soft-pin lifetime.Disableremoves the committed soft pin when the write becomes readable.Preserveretains an unexpired committed deadline across Upsert, but does not preserve an already expired deadline.EnablewithTTL = 0is equivalent to committing ordinary cache.allow_evict_soft_pinned_objects=true, an active soft-pinned object may still be selected by the existing second eviction pass.Write API
Replace the ambiguous boolean write intent with an explicit action:
Request rules:
PRESERVEmust not includesoft_pin_ttl_ms.DISABLEmust not includesoft_pin_ttl_ms.ENABLEusessoft_pin_ttl_mswhen present.ENABLEwithout an override uses the Master'sdefault_kv_soft_pin_ttl.max_kv_soft_pin_ttlis rejected.PRESERVEis the default because a default Upsert should not silently remove an existing eviction-priority deadline. For a new Put, preserving an absent deadline simply creates ordinary cache unless the caller selectsENABLE.The existing C ABI can retain its boolean field for the initial change and translate it as follows:
This keeps existing Go and Rust wrappers functional, although those wrappers will not expose explicit disable or request-level TTL until their APIs are extended.
Master configuration
Add:
The Master validates that:
Deadline arithmetic is checked when the soft pin is committed, not only at Master startup. If
completion_now + ttlcannot be represented bysystem_clock::time_point, the deadline saturates attime_point::max()instead of overflowing.Object state model
The object-level state is:
Pendingis write intent andActiveis committed eviction priority. Starting a write does not immediately apply the requested action because the object may never become readable.The pending action is committed only when:
After commit, Pending is cleared. Later replica completions and duplicate End calls therefore do not refresh the deadline.
Replica IDs are used to associate Pending with the replicas of the current write. End currently carries no write-generation token, so it is not possible to distinguish every stale End from a newer same-client write. Adding a protocol-level operation token is outside this RFC.
Revoke, preemption, and processing cleanup
A partial Revoke must not unconditionally discard Pending.
Pending is retained while at least one eligible PROCESSING replica from the same write can still become the first readable replica. Pending is cleared when:
Committed state is independent from Pending. An Upsert that has not yet become readable does not immediately consume or replace the previous committed deadline.
For size-changing Upsert, an unexpired committed deadline is carried into the replacement metadata. It remains subject to its original deadline while the new replicas are PROCESSING. An expired deadline is not carried into replacement metadata.
Deadline index
Add a private Master-level deadline index without changing
MetadataShard:The index has its own mutex and is ordered after metadata-shard locks in the lock hierarchy. Cleanup never holds the index mutex while acquiring a metadata-shard lock.
The index is updated when:
Enableaction commits;The index is derived runtime state and is not serialized in snapshots.
Expiration cleanup
The existing task-cleanup thread remains responsible for soft-pin expiration; this RFC does not add another thread.
Each cleanup cycle:
deadline <= now.The exact-deadline comparison prevents an old heap entry from clearing a soft pin that was subsequently re-enabled with a newer deadline.
Expiration therefore changes from:
to approximately:
with metadata locks acquired only for shards containing due entries.
TTL updates and stale heap entries
Updating a deadline inserts a new heap entry and updates the latest-registration map. The old heap entry is lazily invalidated because
std::priority_queuedoes not support efficient arbitrary deletion.To prevent repeated TTL updates from growing the heap without bound, rebuild it from live registrations when:
The factor of two limits stale entries to roughly the number of live registrations for large indexes and gives an amortized
O(1)rebuild cost per update. The floor of 4096 avoids rebuilding a small heap after every few updates while still placing an absolute bound on stale entries for small live sets. These are internal constants rather than user-visible configuration.Read and eviction paths
Get,Exist, and group lease refresh stop evaluating or mutating soft-pin state. They update only the ordinary read lease.This removes an additional object-lock acquisition from read-heavy paths and ensures that reads cannot influence object soft-pin lifetime.
Eviction paths still evaluate
now < deadlinewhen deciding priority. Therefore an object receives no soft-pin protection after its deadline even if the periodic cleanup has not yet removed the stored deadline.The soft-pin gauge converges within the existing cleanup interval rather than synchronously on every read. It represents normalized active metadata, not a clock-exact value at every instant between cleanup cycles.
Metrics
Metadata state transitions return a metric delta and an optional deadline-index mutation. The Master applies index and metric changes after releasing the object's spin lock.
The gauge changes once for each logical transition:
Object destruction remains responsible for decrementing an active committed soft pin. Index removal and metric ownership remain separate so stale heap entries cannot double-decrement the gauge.
Snapshot and HA semantics
Snapshots continue to serialize the committed soft-pin deadline already stored in object metadata. The heap and latest-registration map are not serialized.
During restore:
If restoring one snapshot candidate fails and the Master falls back to another candidate, resetting metadata also clears the derived deadline index. This prevents registrations from a failed candidate from leaking into the next attempt.
This RFC does not change the snapshot wire format.
Separation from group retention
Object soft pin and group retention must remain separate priority sources:
Eviction policy may combine those sources, but group retention must not copy or refresh a group deadline into every member's committed object soft pin. This separation allows PR #2835 to use the fixed-lifecycle behavior without reintroducing per-member deadline refresh or state duplication.
Compatibility and rollout
This proposal assumes a coordinated stop-the-world upgrade of Master and C++/Python clients. Mixed old/new Master-client RPC compatibility is not a goal.
Compatibility implications:
with_soft_pinfield is a source-level breaking change.EnableorPreserve.Alternatives considered
Continue lazy expiration on access
This avoids a background index but leaves metrics and metadata stale indefinitely for cold objects and ties cleanup behavior to read traffic.
Periodically scan all metadata
This is simple and exact at the sweep interval, but its cost scales with total object count rather than the number of active or expiring soft pins.
Put one heap in every metadata shard
This avoids a global index mutex but changes
MetadataShard, duplicates heap management across 1024 shards, and requires every cleanup cycle to inspect many independent heaps. It is more invasive than needed for the initial implementation.Use a timing wheel or indexed mutable heap
These structures can reduce stale entries or update cost, but introduce substantially more implementation and synchronization complexity. A min-heap plus latest-registration map is sufficient for the expected TTL granularity and update rate.
Non-goals
Feedback requested
The RFC especially requests feedback on:
PRESERVEas the default write action;with_soft_pinin C++ and Python;Before submitting a new issue...
@github-actions[bot] commented on GitHub (Jul 21, 2026):
Thanks for opening this issue, @Lin-z-w!
99333079A maintainer will triage this when possible. To help us respond faster, please include:
Useful links: Documentation · Contributing guide
@github-actions[bot] commented on GitHub (Oct 20, 2026):
This issue has had no activity for 90 days and will be closed in 7 days if there is no further activity. Please comment or react if it should stay open.
@github-actions[bot] commented on GitHub (Oct 27, 2026):
Closing due to 3 months of inactivity. If this is still relevant, please comment and we can reopen.