API
가 트랜잭션
을 수행하는데, 트랜잭션 내부
에서 외부 API
를 요청한다. 외부 API
를 요청하는 이유는
외부 API
의 응답 결과에 따라 현재 트랜잭션에서 처리되고 있는 작업을 커밋할 지? 롤백할 지? 판단하기 위해서이다.
즉, 현재 API
와 외부 API
에서 처리하는 데이터의 일관성을 유지
하기 위해 그렇다. 근데 위와 같은 처리할때의 장점은 무엇이고, 단점은 무엇인지를 정리하고, 단점이 치명적이라면, 이를 해결할 방법은 무엇이 있는지 정리하고자 한다.
1. 클라이언트로 부터 요청
2. 트랜잭션 시작
3. 쿼리 실행 (200ms 소요)
4. 외부 API 요청 및 응답 (500ms 소요)
5. 트랜잭션 종료
5-1. 외부 API 응답이 성공이면, 트랜잭션 커밋
5-2. 외부 API 응답이 에러이면, 트랜잭션 롤백
6. 클라이언트로 응답
- 트랜잭션의
처리 시간
은700ms
가 소요된다. - 클라이언트에 응답하기까지의
Latency
는700ms
가 소요된다.
외부 API
응답 결과(실패 혹은 장애 발생)에 따라 트랜잭션을 커밋하고, 롤백할 수 있기 때문에현재 API
와외부 API
에서각각의 DB 데이터 일관성
을 보장할 수 있다.
외부 API
응답 시간이 빈번하게 지연되는 상황이면,현재 API
의 다른 스레드들은DB 커넥션
을 획득하기 위해 대기하거나, 타임아웃 발생할 가능성이 크며,병목 현상
이 발생하게 된다.병목 현상
으로 인해현재 API
의 처리 성능은 떨어지게 된다.
- 만약에
4
,5
번 작업 사이에 예외가 발생하면,현재 API
의트랜잭션은 롤백
되고,외부 API
의트랜잭션은 커밋
된 상태이므로데이터 일관성을 보장할 수 없다.
DB 서버로 커밋을 할 시점
에 DB 서버가 순간 장애로 인해 커넥션을 강제로 종료했거나, DB 서버가 다운된 경우
- Spring
@Transactional
의 전파 레벨로 비유 하자면 다음과 같다.REQUIRED
전파 레벨로 트랜잭션을 시작하고,REQUIRES_NEW
전파 레벨을 통해 물리적으로 다른 트랜잭션을 추가로 실행한 상황에서REQUIRES_NEW
로 실행된 트랜잭션은 커밋하고,REQUIRED
로 실행된 부모 트랜잭션은 롤백인 된 상황이랑 똑같다. 이에 따라REQUIRES_NEW
로 실행된 트랜잭션은 이미 커밋 되었기 때문에 롤백을 할 수 없다. 즉,데이터 일관성을 보장할 수 없는 상황이다.
1. 클라이언트로 부터 요청
2. 트랜잭션 시작
3. 쿼리 실행 (200ms 소요)
4. 트랜잭션 종료 (커밋 or 롤백)
5. 외부 API 요청 및 응답 (500ms 소요)
6. 클라이언트로 응답
- 트랜잭션의
처리 시간
은200ms
가 소요된다. - 클라이언트에 응답하기까지의
Latency
는700ms
가 소요된다.
- 트랜잭션이 위의 상황보다 빠른
200ms
이내에 처리되고, 쿼리 실행만 하기 때문에 다른 스레드에서DB 커넥션
을 상대적으로 빨리 확보하여 처리한다. - 다른 스레드에서는
DB 커넥션
을 빠르게 확보하여, 처리하기 때문에API
의전체 성능
이 상대적으로 좋아진다.
현재 API
에서 트랜잭션을 커밋한 상황인데,외부 API
가 어떠한 에러에 의해서 롤백 되었다면,데이터 일관성을 보장하지 않는다.
Saga Pattern
,2-Phase Commit
,Outbox Pattern
기법들을 사용하여, 분산된 서버 환경에서 데이터 일관성을 보장하도록 구현해야 하는데,구현 복잡도가 높다.
첫 번째
작업의 트랜잭션처리 시간
은700ms
에 수행되며,두 번째
작업의 트랜잭션처리 시간
은200ms
에 수행된다.- 즉,
두 번째
작업의 트랜잭션 처리가 더 빨리 되고, 이에 따라DB 커넥션
을 더 빨리 반납하게 되므로API
의전체 성능
이 상대적으로 더 좋다.
- 즉,
- 두 개의 작업은
Latency
가700ms
에 수행되며, 동일한Latency
를 갖는다. 첫 번째
작업은 분산된 서버 환경에서 데이터 일관성을 확실하게 보장할 수 있는가?- 위에서 언급했던
REQUIRED
,REQUIRES_NEW
비유를 통해 확인해보자면, 확실하게 보장할 수 없다.
- 위에서 언급했던
두 번째
작업은 분산된 서버 환경에서 데이터 일관성을 확실하게 보장할 수 있는가?현재 API
가 커밋되고,외부 API
처리 과정에서 롤백이 되면, 데이터 일관성을 확실하게 보장할 수 없다.
- 처음에 빠르게 개발해야 되는 상황에서는
첫 번째
작업을 선택해서 비즈니스를 구현하는데 집중하자 - 시간이 넉넉하다면,
두 번째
작업을 선택하여현재 API
의성능을 높이고
,분산 트랜잭션
,보상 트랜잭션
을 통해데이터 일관성을 유지
하도록 하자Saga Pattern
,2-Phase Commit
,OutBox Pattern