Summary#
Lease 기반 core-sync worker 설계에서 가장 위험한 실패 모드는 “lease가 있으므로 단일 writer가 보장된다”는 착각이다. Lease는 시간, 네트워크 지연, GC pause, 프로세스 정지, clock skew, 저장소 지연의 영향을 받기 때문에 stale lease holder가 만료 이후에도 쓰기를 계속할 수 있다. 이때 새 worker가 lease를 획득하면 split-brain writer 상태가 발생하고, 동일 sync batch 또는 동일 mutation이 중복 적용될 수 있다.
안전한 설계의 핵심은 lease 자체를 권한으로 보지 않고, 모든 write path에 단조 증가하는 fencing token 또는 epoch를 포함시키는 것이다. downstream 저장소는 더 낮은 token의 쓰기를 거부해야 한다. 또한 lease handoff 이후 replay는 idempotency key, per-record version, compare-and-swap, processed-event log, cursor checkpoint의 원자적 갱신을 통해 중복 적용에 견딜 수 있어야 한다.
Key Points#
- Lease expiry는 writer 정지를 보장하지 않는다
- Lease가 만료되었다는 것은 coordinator 관점에서 새 소유자를 뽑을 수 있다는 뜻이지, 기존 worker가 실제로 멈췄다는 뜻은 아니다.
-
기존 worker는 긴 GC pause, scheduler stall, 네트워크 partition, I/O hang 이후 깨어나 자신이 아직 owner라고 믿고 write를 계속할 수 있다.
-
Clock skew가 있는 lease 설계는 특히 취약하다
- lease 판단에 각 노드의 local wall clock을 직접 사용하면, 빠른 시계 또는 느린 시계 때문에 lease 만료·갱신 판단이 엇갈릴 수 있다.
- lease duration은 clock drift, network delay, stop-the-world pause보다 충분히 커야 하지만, 이것만으로 안전성이 증명되지는 않는다.
-
가능하면 lease authority는 단일 일관성 저장소의 revision, session, zxid, term, epoch 같은 논리적 순서를 사용해야 한다.
-
Split-brain writer는 sync 시스템에서 중복 apply로 나타난다
-
두 worker가 같은 tenant, shard, stream, cursor range를 동시에 처리하면 다음 문제가 생긴다.
- 같은 remote event를 두 번 local DB에 반영
- 같은 tombstone 또는 upsert를 중복 처리
- cursor가 뒤로 가거나 잘못 advance됨
- side effect성 webhook, notification, export job이 중복 실행
- conflict resolver가 실제보다 더 많은 concurrent update를 관측
-
Fencing token은 lease보다 강한 write guard다
- lease를 획득할 때마다 coordinator가 단조 증가 token을 발급한다.
- worker는 모든 write, checkpoint, side effect enqueue 요청에 token을 포함한다.
- downstream 저장소는 현재 기록된 token보다 낮은 token의 요청을 거부해야 한다.
-
이 방식은 stale worker가 뒤늦게 깨어나도 “오래된 owner”의 write를 차단한다.
-
Fencing token은 write target이 검증해야 의미가 있다
- token을 로그에만 남기거나 worker 내부에서만 확인하면 stale writer 방지 효과가 약하다.
- 실제 보호 대상인 DB row, queue, object store manifest, checkpoint table, external side-effect gateway가 token 비교를 수행해야 한다.
-
예:
UPDATE sync_state SET ... WHERE shard_id = ? AND lease_token = ?또는WHERE incoming_token >= current_token형태의 조건부 쓰기. -
Lease renewal과 checkpoint advance는 분리해서 생각해야 한다
- lease renewal 성공이 곧 batch 처리 성공을 의미하지 않는다.
- checkpoint는 해당 batch의 durable apply가 끝난 뒤 원자적으로 advance되어야 한다.
-
apply와 checkpoint가 분리되어 있으면 crash 시 이미 반영한 이벤트를 다시 replay할 수 있으므로 idempotent apply가 필요하다.
-
Handoff-safe replay 원칙
- 새 owner는 이전 owner가 어디까지 안전하게 처리했는지 checkpoint에서 시작해야 한다.
- checkpoint보다 이후 구간은 중복 replay될 수 있다고 가정한다.
- replay 대상 operation은 deterministic하고 idempotent해야 한다.
- 각 event에는 stable event id, source version, object version, mutation id 또는 idempotency key가 있어야 한다.
-
side effect는 “DB 반영”과 직접 결합하지 말고 outbox 패턴처럼 dedupe 가능한 durable queue를 거치는 편이 안전하다.
-
권장 상태 모델
lease_ownerlease_token또는epochlease_expires_at, 단 이것만으로 write 권한을 판단하지 않음checkpointcheckpoint_tokenlast_applied_event_id또는 per-objectsource_version-
handoff_started_at,previous_owner,recovery_reason같은 운영 진단 필드 -
권장 write 흐름 1. worker가 coordinator 또는 DB에서 shard lease 획득 2. coordinator가 새 fencing token 발급 3. worker가 token을 메모리에 보관하되, 모든 write 요청에도 포함 4. apply 시 target row 또는 sync state가 token을 검증 5. batch apply 완료 후 checkpoint를 token 조건부로 advance 6. token mismatch, stale token rejection, lease lost 감지 시 worker는 즉시 processing loop를 중단 7. 새 owner는 마지막 durable checkpoint부터 replay
-
테스트해야 할 failure injection
- lease 획득 직후 worker process pause
- lease renewal 직전 긴 GC pause
- DB write는 성공했지만 checkpoint update 전 crash
- checkpoint update는 실패했지만 event apply는 일부 성공
- old owner와 new owner가 동시에 같은 batch write
- clock skew가 큰 노드에서 lease expiry 판단
- network partition 후 old owner가 뒤늦게 write 시도
- token이 없는 legacy write path가 남아 있는 경우
Cautions#
- Lease만으로 exactly-once processing을 보장한다고 표현하면 안 된다. 대부분의 실용적 sync worker는 replay와 중복 적용 가능성을 전제로 at-least-once 처리에 idempotency와 dedupe를 결합한다.
- fencing token은 downstream이 token을 비교·거부할 수 있을 때만 효과가 있다. 외부 API가 token 검증을 지원하지 않는다면 outbox, idempotency key, compensating action 같은 별도 장치가 필요하다.
- wall-clock 기반 TTL lock은 구현이 단순하지만, clock skew와 pause time의 상한을 운영적으로 보장하지 못하면 안전성 주장이 약하다.
- Redis 기반 lock 또는 Redlock류 설계는 사용 맥락에 따라 논쟁이 있다. efficiency 목적의 중복 방지와 correctness 목적의 단일 writer 보장은 구분해야 한다.
- handoff replay를 안전하게 하려면 “어디까지 읽었는가”가 아니라 “어디까지 durable하게 적용했고 checkpoint까지 확정했는가”를 기준으로 복구해야 한다.
- 공개 자료만으로 특정
core-sync구현의 실제 장애 이력을 확인한 것은 아니다. 위 내용은 분산 시스템 lease/lock 설계에서 알려진 일반 failure mode를core-synccapsule 초안에 맞춰 정리한 것이다.
Sources#
- https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
- https://redis.io/docs/latest/develop/clients/patterns/distributed-locks/
- https://static.googleusercontent.com/media/research.google.com/en//archive/chubby-osdi06.pdf
- https://zookeeper.apache.org/doc/r3.9.3/recipes.html
- https://etcd.io/docs/v3.5/learning/api_guarantees/
- https://etcd.io/docs/v3.5/dev-guide/api_concurrency_reference_v3/
Related#
- Bidirectional Sync Engine Failure Modes: Watermarks, Tombstones, Conflict Resolution, and Clock-Skew-Safe Change Capture
- Core API Idempotency-Key Contracts: Request Fingerprinting, Replay Semantics, Concurrent Duplicate Suppression, and Expiry Failure Modes
- Core Sync Incremental Replication: High-Water Marks, Tombstone Propagation, and Clock-Skew Failure Modes
Sagwan Revalidation 2026-07-26T22:40:28Z#
- verdict:
ok - note: lease·fencing token·idempotent replay 권장안은 현재도 표준 practice다.
Sagwan Revalidation 2026-07-29T04:11:34Z#
- verdict:
ok - note: lease·fencing token·idempotent replay 권장안은 현재도 표준적이다.
Sagwan Revalidation 2026-07-31T12:00:13Z#
- verdict:
ok - note: lease·fencing·idempotent replay 권장안은 현재 practice와 부합함