mirror of
https://github.com/kvcache-ai/Mooncake.git
synced 2026-11-05 01:17:55 +00:00
[GH-ISSUE #1650] [RFC]: HA OpLog Store Abstraction Layer #484
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#484
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 @duhaode520 on GitHub (Mar 13, 2026).
Original GitHub issue: https://github.com/kvcache-ai/Mooncake/issues/1650
Introduction
The HA (High Availability) system introduced in RFC #1200 and implemented in PR #1515 uses etcd as the sole OpLog storage backend. While etcd provides strong consistency and a built-in Watch mechanism, the tight coupling between all HA components and etcd makes it impossible to swap storage backends, difficult to unit test without a running etcd cluster.
This RFC introduces an abstraction layer that decouples upper-layer components (
OpLogManager,OpLogApplier,OpLogReplicator) from the etcd-specific implementation, enabling pluggable storage backends (HDFS, S3, local filesystem, etc.) in the future. The change is interface extraction only — no new backends are introduced. The existingEtcdOpLogStorebecomes the first (and currently only) implementation of the new abstract interfaces.Motivation
The OpLog subsystem is tightly coupled to etcd as the sole storage backend. All four core components directly depend on the concrete
EtcdOpLogStoreclass:OpLogManagershared_ptr<EtcdOpLogStore>OpLogApplierEtcdOpLogStorebehind#ifdef STORE_USE_ETCDOpLogWatcherEtcdHelperfor Watch/Read, owns its ownEtcdOpLogStore, duplicatesDeserializeOpLogEntryHotStandbyServiceEtcdOpLogStoreat 4 separate sitesThis coupling means: (1) no alternative storage backend can be used without rewriting all consumers; (2) core replication logic cannot be unit tested without a running etcd cluster;
Goals
OpLogStoreandOpLogChangeNotifierabstract interfaces so new backends (HDFS, S3, etc.) can be added without modifying consumersMockOpLogStorefor fast, deterministic unit tests — enable the 23+ previously-SKIP'd test casesOpLogWatchermonolith into focused components with clear ownership boundariesEtcdOpLogStoreconstruction sitesNon-Goals: Implementing new storage backends, changing serialization format, modifying etcd key schema, or changing the HA election mechanism.
Proposal
1. Architecture Comparison: Before vs After
(1) Before: etcd-Coupled Architecture (PR #1515)
(2) After: Abstracted Architecture (This RFC)
Key differences:
OpLogReplicatoris a thin orchestrator — all etcd logic lives inEtcdOpLogChangeNotifierOpLogApplierreceivesOpLogStore*via dependency injection, no#ifdef2. Component Dependency Comparison
3. Core Interfaces
(1) OpLogStore — Storage Abstraction
Key Design Decisions:
a.
ReadOpLogSinceWithRevisionis NOT in the interface. The etcd revision is a backend-specific concept for "read-then-watch" consistency. Polling-based backends usesequence_idas the checkpoint. This method remains onEtcdOpLogStoreonly.b. Snapshot-related methods are included. OpLog GC depends on snapshot boundaries —
CleanupOpLogBeforemust not delete entries newer than the latest snapshot'ssequence_id, so this mapping belongs in the same backend.(2) OpLogChangeNotifier — Replication Abstraction
Implementations:
EtcdOpLogChangeNotifierPollingOpLogChangeNotifierReadOpLogSinceOpLogStore(3) OpLogStoreFactory — Centralized Creation
The factory replaces 4 scattered
EtcdOpLogStoreconstruction sites. Adding a new backend requires only:OpLogStore+OpLogChangeNotifierOpLogStoreTypeOpLogStoreFactory::Create(4) Serialization Extraction
Previously duplicated as private methods in both
EtcdOpLogStoreandOpLogWatcher. Now a single shared utility using JSON format with base64-encoded binary payloads.4. OpLogWatcher Refactoring: Before vs After
This is the most significant structural change. The monolithic
OpLogWatcheris split into focused components:OpLogWatcher)EtcdHelpercalls + ownEtcdOpLogStoreEtcdOpLogChangeNotifierDeserializeOpLogEntryoplog_serializer.hWatchCallbackContext*managed inlineChangeNotifierCallbackContextencapsulatedOpLogChangeNotifierfor unit tests5. Upper-Layer Component Changes
shared_ptr<EtcdOpLogStore>shared_ptr<OpLogStore>SetEtcdOpLogStore()SetOpLogStore()PersistEntryToEtcd()PersistEntry()EtcdOpLogStoreinternallyOpLogStore*via constructor#ifdef STORE_USE_ETCDguardsif (oplog_store_)GetEtcdOpLogStore()private methodoplog_store_pointer (no lazy init)OpLogWatcher(575 LOC)OpLogReplicator(~80 LOC)etcd_endpointsstringOpLogChangeNotifier*+OpLogApplier*new EtcdOpLogStore(...)directlyOpLogStoreFactory::Create(ETCD, id, READER)#include "etcd_oplog_store.h"#include "oplog_store_factory.h"6. etcd-Specific Implementation Details
These details are unchanged from PR #1515 and are hidden behind the abstract interfaces. See RFC #1200 and
docs/oplog-store-abstraction-architecture.mdfor full HA flow sequences (startup sync, gap recovery, watch reconnect, promotion).7.
#ifdef STORE_USE_ETCDStrategyEtcdOpLogStore,EtcdOpLogChangeNotifier#ifdef STORE_USE_ETCDOpLogStoreFactory#ifdefin.cppfor etcd caseOpLogManager#ifdef— depends on abstractOpLogStoreOpLogApplier#ifdef STORE_USE_ETCDfor lazy initif (oplog_store_)OpLogWatcher→OpLogReplicator#ifdeffor etcd watchOpLogChangeNotifierHotStandbyService#include "etcd_oplog_store.h"#include "oplog_store_factory.h"Testing Strategy
New Test Infrastructure
MockOpLogStore(tests/hot_standby_ut/mock_oplog_store.h):std::map<uint64_t, OpLogEntry>storageSetWriteError(),SetReadError()CreateChangeNotifier()returns a mock notifierNew and Enabled Tests
oplog_serializer_testoplog_applier_test(gap resolution)oplog_replicator_test(event handling)oplog_manager_test(boundary)File Organization
New Files
include/oplog_store.hOpLogStoreabstract interfaceinclude/oplog_change_notifier.hOpLogChangeNotifierabstract interfaceinclude/oplog_serializer.hinclude/oplog_store_factory.hinclude/etcd_oplog_change_notifier.hsrc/oplog_serializer.cppsrc/oplog_store_factory.cppsrc/etcd_oplog_change_notifier.cpptests/hot_standby_ut/mock_oplog_store.htests/hot_standby_ut/oplog_serializer_test.cppModified Files
include/etcd_oplog_store.hOpLogStore, addsoverrideinclude/oplog_manager.hEtcdOpLogStore→OpLogStoreinclude/oplog_applier.hEtcdOpLogStore→OpLogStore, DIinclude/oplog_replicator.hoplog_watcher.h, now depends onOpLogChangeNotifiersrc/etcd_oplog_store.cppsrc/oplog_manager.cppSetOpLogStore(),PersistEntry()src/oplog_applier.cpp#ifdefsrc/oplog_replicator.cppoplog_watcher.cpp)src/hot_standby_service.cppOpLogStoreFactoryFuture Work
Alternative Storage Backends
Key Design Points Summary
OpLogStoremirrorsEtcdOpLogStore's public API exactly — no speculative methodsBefore submitting a new issue...
@duhaode520 commented on GitHub (Mar 13, 2026):
@00fish0 @Libotry, RFC about pluggable abstraction design for Oplog storage backend is available, do you have time to review this? Looking forward to your suggestion.
@github-actions[bot] commented on GitHub (Jun 12, 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 (Jun 20, 2026):
Closing due to 3 months of inactivity. If this is still relevant, please comment and we can reopen.