분산 서버의 시계로 last-write-wins를 믿어도 될까?
서버마다 시계가 조금씩 다르면 타임스탬프가 큰 쓰기를 남기는 last-write-wins가 실제로는 나중에 쓴 값을 버립니다. 컨테이너마다 시간을 어긋나게 해서 나중 쓰기가 사라지는 과정을 재현하고, Redis 시계로 모으는 방법의 한계와 버전 번호로 순서를 정하는 방법을 확인합니다.
서버마다 시계가 조금씩 다르면 타임스탬프가 큰 쓰기를 남기는 last-write-wins가 실제로는 나중에 쓴 값을 버립니다. 컨테이너마다 시간을 어긋나게 해서 나중 쓰기가 사라지는 과정을 재현하고, Redis 시계로 모으는 방법의 한계와 버전 번호로 순서를 정하는 방법을 확인합니다.
gRPC 호출은 데드라인을 걸지 않으면 응답이 올 때까지 기다리고, 하위 서비스 하나가 느려지면 기다리는 호출이 작업 스레드를 붙잡아 상관없는 요청까지 늦어집니다. Python gRPC로 A→B→C 호출 체인을 만들어 데드라인 없음과 남은 시간 전파를 비교하고, 남은 시간을 넘기지 않을 때 하위 서비스에 남는 작업을 확인합니다.
서비스마다 DB가 나뉘면 결제와 재고 차감을 한 트랜잭션으로 묶을 수 없어서, 실패한 단계 앞의 작업은 보상 트랜잭션으로 되돌려야 합니다. Kafka 4.3과 PostgreSQL 17로 2PC가 남기는 잠금을 보고, 오케스트레이션 Saga로 환불 흐름과 보상 실패의 재시도를 직접 확인합니다.

Redis의 `SET NX PX` 락은 TTL이 지나면 풀리기 때문에, 작업 중에 멈췄다 깨어난 서버와 새로 락을 잡은 서버가 같은 데이터를 함께 고칠 수 있습니다. Redis 8.10과 PostgreSQL 17로 락 만료 뒤 갱신 손실과 watchdog 연장의 한계를 재현하고, 펜싱 토큰으로 늦게 온 쓰기를 DB에서 거절합니다.
DB 커밋과 Kafka 전송은 한 트랜잭션으로 묶이지 않아, DB를 먼저 커밋하고 전송이 실패하면 이벤트가 사라집니다. Kafka 4.3과 PostgreSQL 17로 이 실패를 재현하고, outbox 테이블과 폴링 릴레이를 직접 만들어 릴레이가 죽을 때 생기는 중복까지 확인합니다.
