diff --git "a/docs/database/01.\353\263\265\354\240\234\354\247\200\354\227\260.md" "b/docs/database/01.\353\263\265\354\240\234\354\247\200\354\227\260.md" new file mode 100644 index 00000000..7db38beb --- /dev/null +++ "b/docs/database/01.\353\263\265\354\240\234\354\247\200\354\227\260.md" @@ -0,0 +1,59 @@ +# DB 복제 지연 + +- Main-Replica 구조에서 발생 +- Main DB(Write DB)에서 데이터 변경이 일어난 후, Replica DB(Read DB)로의 복제가 즉시 이루어지지 않는 경우를 `복제가 지연됐다`고 표현함 +- 이런 지연이 생기는 동안에 애플리케이션 로직이 Replica DB를 조회하면 아직 반영되지 않은 예전 데이터 조회 + +## 시나리오 + +```kotlin +// 사용자의 계정 잔액을 증가시키는 로직 +fun increaseBalance(userId: String, amount: Int) { + // 1. Main DB에 사용자 잔액 증가 반영 + userRepository.increaseBalance(userId, amount) + + // 2. 이벤트를 생성하여 다른 서비스에 잔액 변경을 알림 + eventPublisher.publishBalanceIncreasedEvent(userId, amount) + + // 3. 현재 잔액을 Replica DB에서 조회 + val currentBalance = userRepository.getBalance(userId) + + // 4. 현재 잔액이 특정 조건을 만족하면 보너스 지급 + if (currentBalance >= 10000) { + bonusService.grantBonus(userId) + } +} +``` + +> 복제 지연이 발생하면, 3번 Replica DB에서 잔액이 10,000원 이상 될 것으로 예상했지만 1번의 Main DB에 잔액 증가가 반영되기 전 데이터를 읽어오기 때문에 보너스가 지급되지 않는다. + +![image](https://github.com/jun108059/til/assets/42997924/7f5b1ad6-3efa-494a-90d7-ff3364a24590) + + +## 해결 방법 + +### 1. MainDB 읽기 + +- 해당 로직에서는 insert-select를 동일한 MainDB에 query하도록 할 수 있다. +- 단점은 Main DB에 부하가 발생한다 + +### 2. 로직 설계 + +- 로직을 설계할 때, 복제 지연 가능성을 고려하여 데이터 불일치가 발생해도 시스템이 제대로 동작하도록 설계 +- ex) insert 후 의도적으로 지연시간을 두어, 복제가 완료된 이후에 select 한다 + +> 🤔 이렇게 로직을 설계하려면 로직 처리 지연 시간을 얼마나 둬야 되는지, 복제 지연이 얼마나 길게 발생하는지 알아야되는데 어떻게 파악할까? + +#### 복제 지연 시간 모니터링 + +- DB 복제 지연 모니터링 방법은 Grafana, Prometheus, Datadog 등의 솔루션을 통해 시각화하고 alert도 연동할 수 있다! +- 아래 그래프를 보면, 복제 지연 시간을 y축 "초"로 확인할 수 있다. + +image + +### 3. 분산 트랜잭션을 통한 데이터 일관성 유지 + +- 분산 트랜잭션(Distributed Transaction)은 여러 시스템 간에 데이터의 일관성을 유지하기 위해 사용하는 기술이다 +- 각 시스템이 개별적으로 트랜잭션을 관리하는 대신, 여러 시스템이 참여하는 전체 트랜잭션을 관리하여 모든 시스템의 데이터 상태를 일관되게 유지하려는 목적이 있다 +- 2단계 커밋(2-Phase Commit)과 3단계 커밋(3-Phase Commit), 사가 패턴(Saga Pattern) 등이 분산 트랜잭션을 구현하는 데 사용되는 대표적인 알고리즘과 패턴이다 +- 자세히 다루기는 내용이 많기 때문에 이후에 따로 정리할 예정이다