외부 연동과 트랜잭션 처리
DB 연동과 외부 연동을 함께 할때는, 오류 발생 시 DB 트랜잭션을 어떻게 처리할지 잘 판단해야한다. 흔히 발생할 수 있는 2가지 상황
- 외부 연동에 실패했을 때 트랜잭션 롤백
- 외부 연동 성공했지만 DB 연동에 실패해 트랜잭션 롤백 외부 연동에 실패시 트랜잭션을 롤백
트랜잭션 범위 안에서 외부 연동 실패의 경우, 트랜잭션 롤백이 가능하다.
하지만, 읽기 타임아웃이 발생해 트랜잭션이 롤백할 때는 외부 서비스가 실제로는 성공적으로 처리했을 가능성을 고려해야한다.
트랜잭션은 롤백했는데 외부 서비스가 실제 성공시 2가지 방법 중 하나를 검토하자.
- 일정 주기로 두 시스템간 데이터 일치 확인해보고 보장
- 예를들어 주문 서비스, 포인트 서비스가 하루에 한 번씩 전날 포인트 사용내역을 비교해 불일치가 있는지 확인하는 식
- 성공 확인 API 호출
- 읽기 타임아웃이 발생한경우 일정 시간 후에 이전 호출이 실제로 성공했는지 확인하는 API를 호출. 이때 성공 응답이 오면 트랜잭션 지속하고 아니면 롤백
- 읽기 타임아웃 발생하면 일정 시간뒤 그냥 무조건 취소 API를 호출. 트랜잭션은 그냥 롤백하면됨
외부 연동은 성공했는데 DB연동에 실패해 트랜션을 롤백
DB가 실패하면 취소 API를 호출한다. 되돌리는 방법을 떠올리면됨.
외부 연동이 느려질 때 DB 커넥션 풀 문제
DB 트랜잭션 범위 안에서 외부 연동을 수행할 때 트랜잭션 처리 외에도 주의해야 할 점이 있다. 바로 외부 연동이 느려지며 생기는 커넥션 풀 부족 현상이다. 예를 들어, 기능 실행에 5초가 걸리는 상황을 생각해보자.
- 커넥션 풀에서 커넥션 가져온다.
- 0.1초 걸리는 DB 쿼리 실행.
- 외부 연동 API 호출(API 실행해 4.8초 소요)
- 0.1초 걸리는 DB 쿼리 실행
- 커넥션 풀에 반환 위 시나리오에서 외부 연동 제외하면, 실제 DB 커넥션이 사용되는 시간은 0.2초에 불과하다. 하지만 외부 연동에 4.8초 걸리면서 커넥션은 총 5초 동안 사용상태로 있게된다. 즉, DB 쿼리를 실행하지 않아도 커넥션이 점유된 상태가 지속되는 것.
DB 처리 시간은 동일한데 단지 외부연동이 길어졌다느 이유로 커넥션 풀이 포화되는 문제가 발생할수 있다!
DB연동과 무관히 외부 연동 실행할 수 있다면, DB 커넥션 사용 전이나 후에 외부 연동 시도하는 방안 고려할 수 있다.
단, 이 방식은 외부 연동이 트랜잭션 범위 밖에 있기에 트랜잭션 커밋 이후 외부 연동이 실패하면 롤백이 불가하다는 점 고려해야한다. 이 경우 실패한 외부 연동에 대한 후처리 반드시 고려해야한다.
후처리 방법으로는 트랜잭션으로 반영된 데이터를 되돌리는 보상 트랜재션 이용 또는 기능 특성에 따라 데이터 후보정 등이 있다.