mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #4996] [RFC]: Valkey as an object storage offload target, with RDMA through Transfer Engine #1268
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#1268
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 @whn09 on GitHub (Oct 27, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/4996
Changes proposed
Motivation
Store offload can write objects to OSS or an S3-compatible service (
ObjectStorageAdapterunderDistributedStorageBackend). Both need a bucket and move every byte over HTTP. Many deployments already run Valkey as an in-VPC cache tier. With the valkey-large-object module (BLOB.*commands), Valkey stores multi-MB binary objects in DRAM or tiered to NVMe, which fits KV-cache objects.An adapter for it gives Store a remote, shared offload tier with no bucket and no filesystem mount. The module can also move object bytes with one-sided RDMA. If its server reaches the owner's buffers through Transfer Engine, offload and load skip the RESP connection and the copies on both ends. Across two r8idn.96xlarge hosts (2 EFA NICs, 600 Gbps), this runs at 57 GB/s for offload and 63 GB/s for load, against 3.4 and 1.3 GB/s over TCP.
Proposed design
Adapter.
ValkeyObjectStorageAdapteris a thirdObjectStorageAdapter, selected withMOONCAKE_DISTRIBUTED_FS_TYPE=valkey.<prefix>/<logical key>. The prefix isMOONCAKE_DISTRIBUTED_ROOT_DIRwithout leading and trailing slashes, as the OSS adapter does. Keys are binary-safe.Put/PutV/GetuseBLOB.TCP_SETandBLOB.TCP_GET,ExistsusesEXISTS,DeleteusesDEL.ListKeysusesSCANwith an escapedMATCHpattern, and gets sizes from pipelinedBLOB.INFO.MOONCAKE_VALKEY_POOL_SIZE, default 8). Batch requests are spread across the pool and pipelined per connection.AUTHis sent on every new connection.Init()fails fast if the server lacksBLOB.TCP_SET.STORE_USE_REDISoption, which already links hiredis. No new dependency.RDMA path (
MOONCAKE_VALKEY_TRANSPORT=rdma).ObjectStorageAdapter::BindTransferEndpoint(segment_name), with a no-op default.DistributedStorageBackendforwards it. In object storage mode,FileStoragebindsclient_->GetSegmentEndpoint(). Other adapters are unchanged.BLOB.RDMA_HELLO <segment>once. The server then opens the owner's segment with its own Transfer Engine.BLOB.RDMA_SET key total_len (rkey addr len).... The server pulls thePutViovecs straight out of the owner's mounted segment, so there is no joining copy.BLOB.RDMA_GET key (rkey addr len), pipelined per connection. The server pushes the object into FileStorage's registered client buffer.Fallback. Correctness never depends on registration.
BLOB.TCP_SETwould return as well are not resent: OOM,WRONGTYPE, max object size, zero length.GetTransportStats()counts RDMA requests, TCP requests and fallbacks.Configuration.
MOONCAKE_VALKEY_{ADDR,USERNAME,PASSWORD,POOL_SIZE,TIMEOUT_MS,TRANSPORT}. The default is TCP, so nothing changes for deployments that do not setMOONCAKE_DISTRIBUTED_FS_TYPE=valkey.Dependencies
fabric-provider MooncakeTe). It is prototyped in whn09/valkey-large-object@mooncake-te-backend and is not in a module release yet. The TCP path works with released modules.remote_accessible=false, so peers cannot target it. On EFA this relies on #4976, which makes the EFA transport honor that flag.Trust model
With RDMA, the Valkey server reads and writes the owner's registered memory, the mounted segment and the client buffers. This is the same trust any Transfer Engine peer that can open the segment already has. Run the server inside the same trust boundary as the Store clients. TCP mode exposes no memory.
Limitations
max-object-size(512 MiB by default), so offloading those fails.maxmemory-policy, and an evicted object reads as missing. Usenoeviction, or size the server for the offloaded data, when offloaded objects must stay readable.te-locations) is what reaches every NIC.Out of scope
Validation (2× r8idn.96xlarge, 2 EFA NICs each, libfabric 2.4, hiredis 1.2.0)
Store runs on one host; Valkey with the module and its TE backend (
te-locations cpu:0,cpu:3) runs on the other, so all traffic crosses hosts.valkey_adapter_live_test, 14 cases:PutV, prefix reads, missing keys, overwrite, binary keys with\0and glob characters,Exists/Delete/ListKeys, empty objects, batches, health check, andDistributedStorageBackendoffload/exists/load/scan.FileStorageTestend to end with a real master and client:LOCAL_DISKreplica per object and the bytes match.efa,P2PHANDSHAKE, 16 × 4 MiB), the server'slargeobj_rdma_read_bytesandlargeobj_rdma_write_byteseach grow by exactly the payload size.Throughput,
PutBatch/GetBatchover 4 GiB per round:RDMA reaches about 85% of line rate. TCP GET is bound by the Valkey server: its main thread and I/O threads sit at 100% CPU.
Implementation: #4991.
Before submitting a new issue...
@github-actions[bot] commented on GitHub (Oct 27, 2026):
Thanks for opening this issue, @whn09!
964527A maintainer will triage this when possible. To help us respond faster, please include:
Useful links: Documentation · Contributing guide