← 기술 목록으로
바이너리 로그 동기화 4.0 — 단순 리플레이를 CDC·멱등 UPSERT로 전환
mysqlbinlog 파이프로 파일을 통째 리플레이하던 고객사 동기화를, binlog 이벤트를 직접 파싱해 UPSERT로 변환·적용하는 Go 기반 CDC 구조로 재설계 — 재시도해도 깨지지 않는 동기화를 만든 작업
기간2025.09 제안 · 2026.01–04 설계·구현·배포
소속래브라도랩스(LabradorLabs)
역할Data Engineer · CDC 전환 제안 및 설계·구현
GoCDCMySQL Binary LogUPSERTSHA256state.yaml
0작업자의 메모
레거시 동기화의 단위는 binlog "파일"이었습니다. 파일 안의 이벤트 하나가 실패해도 파일 전체가 막히고, 어디까지 들어갔는지는 stderr 텍스트를 긁어 세는 수준이라 복구 위치를 특정할 수 없었습니다. 품질 개선 회의에서 CDC 구조 전환을 직접 제안한 이유입니다.
설계 원칙은 한 줄입니다 — 전달은 중복될 수 있어도, 적용은 멱등하게. INSERT/UPDATE를 UPSERT로 변환하면 같은 이벤트를 두 번 적용해도 결과가 같으니 재시도가 두렵지 않은 시스템이 됩니다. at-least-once 전달에 멱등 적용을 더해 사실상 exactly-once 의미론을 얻는, 분산 데이터 시스템의 정석 패턴입니다.
1배경
레거시(v2/v3) Updater는 mysqlbinlog 유틸리티를 파이프로 실행해 binlog를 타겟 DB에 그대로 밀어넣는 단순 리플레이였습니다. SQL을 제어할 수 없으니 중복 키 에러가 나면 수동 개입이 필요했고, DEFINER 절·Virtual Column처럼 고객사 환경에서 깨지는 구문도 거를 수 없었습니다.
Before
파일 단위 All-or-Nothing 리플레이 → 이벤트 하나의 실패가 파일 전체를 막음, 중복 적용 시 에러, 복구 위치 추적 불가
After
이벤트 단위 파싱·변환·적용 → 멱등 UPSERT로 재시도 안전, state.yaml 체크포인트로 실패 지점부터 정확히 재개
2한 일
- binlog 직접 파싱 → SQL 변환 엔진을 Go로 구현 — INSERT/UPDATE를
INSERT ... ON DUPLICATE KEY UPDATE(UPSERT)로 변환해 재실행 시에도 중복 입력이 발생하지 않는 멱등성 확보
- 타겟 환경에 맞춘 SQL Sanitization — DEFINER 절 제거, GRANT 문 스킵,
GENERATED ... VIRTUAL 컬럼은 information_schema 조회로 자동 식별해 INSERT에서 제외
- 무결성 검증을 MD5에서 SHA256으로 교체 — 서버가 보낸 평문 해시와 클라이언트가 복호화 후 계산한 해시를 대조해 전송 깨짐·키 오류를 즉시 감지
- Smart Polling 프로토콜 설계 — 마지막 수신 해시를 헤더로 보내 변경 없으면 304 Not Modified, 파일 생성 중이면 404 대신 202 Accepted로 "에러"와 "대기"를 구분
- 분산 TXT 상태 파일을 state.yaml 하나로 통합 — 인스턴스별·모드별(download/import) 커서를 구조화하고, import 실패 시 download 커서를 되돌리고 손상 파일을 지우는 자동 롤백 내장
- Python 프로토타입을 Go로 재작성 + 커밋 전략 최적화 — 메모리 사용량과 처리 속도 한계를 확인하고 전환, 비대한 테이블일수록 심해지던 트랜잭션 커밋 오버헤드를 함께 해소. binlog 파일당(33만~54만 변경 이벤트) 처리 시간 SSD 평균 96초 → 39초(2.56배), HDD source 인스턴스는 평균 3.0배·최대 5배 단축
- 장애 시나리오 테스트 매트릭스 설계·수행 — 실패 유형을 코드로 분류(Deadlock 113·truncation 110은 skip 후 전진, 연결 끊김 102·복호화 실패 114는 동일 파일 재시도)하고 모드별·멀티 소스·proxy 다중 체인·retention까지 v2 대비 검증
A아키텍처 (데이터 흐름)
Source DB사내 main / source 인스턴스
binlog →
Download Server v4실시간 암호화 스트리밍 · Smart Polling
암호화 파일 →
Updater (Go)복호화 → 파싱 → UPSERT 변환
SQL 적용 →
고객사 Target DBon-premise
다운로드와 임포트를 별도 모드로 분리해 각자의 커서(next_index)로 진행하고, 임포트 실패 유형에 따라 파일 재다운로드(손상)와 임포트만 재시도(DB lock·일시 장애)를 구분해 복구합니다.
3임팩트
정합성 — 멱등 UPSERT + 이벤트 단위 제어로 중복·누락 없이 재시도 가능, 사실상 exactly-once 적용
자동 복구 — 체크포인트 롤백이 내장되어 파일 손상·임포트 실패가 사람 개입 없이 다음 주기에 스스로 복구
처리 속도 — binlog 파일당 SSD 평균 96초 → 39초(2.56배), HDD 최대 5배. 데이터가 클수록 격차 확대
4역할
2025년 9월 품질 개선 회의에서 Binlog Shipping의 파일 단위 한계를 제기하며 CDC 구조 전환을 제안했고, 2026년 1분기에 설계·구현을 맡아 4월 배포까지 진행했습니다. 비교 검토(Debezium·Maxwell·커스텀)부터 Go Updater의 파싱·변환·상태 관리 설계, SSD/HDD 환경별 v2 대비 성능 측정까지 문서로 남기며 작업했습니다.
같은 v4에서 진행한 AES-256-GCM 암호화 전환(동기화 ③), 동기화 상태를 지켜보는 Grafana 모니터링(동기화 ④)과 함께 Binlog shipping service 4.0을 구성. 수집/배포 DB 경계를 세운 ETL DB 영역 분리에서 출발한 동기화 구조 개선의 현재 지점.