[포스트모텀] Redis Redlock 및 SSE 기반 멀티 에이전트 트랜잭션 동기화 장애 복구
1. 장애 요약
- 발생 일시: 2026-02-25 10:15 KST
- 시스템: SyncVerse Core Orchestrator & A2A MessageHub
- 장애 영향: 대규모 API 스키마 생성 및 CMS 배포 동시 진행 시, 동일한 프로젝트 엔티티에 대해 두 개의 독립적인 Saga 워크플로우 인스턴스가 동시 생성되어 데이터베이스 테이블 스키마 중복 생성 오류(
TableAlreadyExistsException) 발생.
2. 근본 원인 분석 (RCA)
SyncVerse는 멀티 에이전트 간의 동시성 제어를 위해 Redis 분산 락(Redlock 알고리즘)을 사용하고 있었습니다.
핵심 결함 요인
- 고정 Lease Time (30초) 설정: 단순 CRUD 작업에는 충분했으나, AI 모델 추론이 결합된 대규모 코드 생성 및 컴파일 작업(40~60초 소요)에 대해 락 유효 기간이 턱없이 부족했음.
- Watchdog(자동 락 연장) 메커니즘 누락: 작업이 정상 수행 중임에도 불구하고 백그라운드에서 TTL을 주기적으로 연장(Heartbeat Extension)해주는 갱신 스레드가 구현되어 있지 않았음.
3. 해결 조치
(1) 비동기 Lock Watchdog 메커니즘 구축
작업이 종료되거나 컨텍스트가 취소되기 전까지, TTL의 1/3 주기(10초)마다 Redis EXPIRE 명령을 실행하여 락의 유효성을 자동 연장하도록 보강했습니다.
java
@Component
@Slf4j
public class DistributedLockManager {
private final StringRedisTemplate redisTemplate;
private final ScheduledExecutorService watchdogScheduler = Executors.newSingleThreadScheduledExecutor();
public AutoCloseable acquireLock(String lockKey, String lockValue, long leaseTimeSeconds) {
Boolean acquired = redisTemplate.opsForValue()
.setIfAbsent(lockKey, lockValue, Duration.ofSeconds(leaseTimeSeconds));
if (!Boolean.TRUE.equals(acquired)) {
throw new DistributedLockAcquisitionException("락 획득 실패: " + lockKey);
}
// 10초마다 락 연장하는 Watchdog 태스크 등록
ScheduledFuture<?> watchdogTask = watchdogScheduler.scheduleAtFixedRate(() -> {
try {
String currentValue = redisTemplate.opsForValue().get(lockKey);
if (lockValue.equals(currentValue)) {
redisTemplate.expire(lockKey, Duration.ofSeconds(leaseTimeSeconds));
}
} catch (Exception e) {
log.warn("[LockWatchdog] 락 연장 실패 key={}: {}", lockKey, e.getMessage());
}
}, leaseTimeSeconds / 3, leaseTimeSeconds / 3, TimeUnit.SECONDS);
// 자원 해제용 클로저 반환
return () -> {
watchdogTask.cancel(true);
releaseLockSafely(lockKey, lockValue);
};
}
}(2) SSE(Server-Sent Events) 스트림 하트비트 연동
관제 콘솔로 진행 상황을 브로드캐스팅하는 SSE 채널에 15초 단위의 더미 코멘트(:heartbeat\n\n)를 전송하여 프록시/로드밸런서 타임아웃(Idle Timeout 60s)으로 인한 클라이언트 단절을 원천 차단했습니다.
4. 검증 결과
100개 동시 워크플로우 디스패치 부하 테스트(각 작업당 인위적 60초 지연 삽입) 환경에서 검증을 수행했습니다.
- 중복 작업 디스패치 발생 건수: 100건 중 0건 (완전 차단).
- 정상 완료 후 락 반환 지연 시간: 평균 4ms 이내.
- 장애 복구 검증: 프로세스 비정상 강제 종료 시, Watchdog 스케줄러 중단에 따라 30초 후 Redis TTL이 정상 만료되어 데드락(Deadlock)이 발생하지 않음을 확인.