티스토리 뷰
프로젝트 중 사용자가 중복으로 등록되는 이슈로 인해 동시성 제어를 위해
@Retryable을 공부하다가 @Retryable과 @Transactional 의 주석 순서 차이로 인한 프로세스의 순서가 차이가 있음을 발견했습니다.
다음의 두 코드의 차이는 @Transactional
과 @Retryable
어노테이션의 순서에 있습니다. 이 순서 차이로 인해 DataIntegrityViolationException 이 발생했을 때 프로세스에 미치는 영향은 다음과 같습니다.
첫 번째 코드:
@Transactional @Retryable( retryFor = {DataIntegrityViolationException .class}, maxAttempts = 1000, backoff = @Backoff(100) ) public void insertUser(long ticketId) {}
이 경우,
@Transactional
어노테이션이 먼저 적용됩니다. 즉,insertUser
메서드가 트랜잭션 내에서 실행되고, 그 후에@Retryable
어노테이션이 적용됩니다. 따라서 트랜잭션 내에서 DataIntegrityViolationException 이 발생하면 해당 트랜잭션이 롤백되고,@Retryable
에 의해 메서드가 다시 시도됩니다. 재시도된 메서드는 새로운 트랜잭션에서 실행됩니다.두 번째 코드:
@Retryable( retryFor = {DataIntegrityViolationException .class}, maxAttempts = 1000, backoff = @Backoff(100) ) @Transactional public void insertUser(long ticketId) {}
이 경우,
@Retryable
어노테이션이 먼저 적용됩니다. 즉,insertUser
메서드는 트랜잭션 시작 전에 재시도 로직이 먼저 적용됩니다. 재시도 로직은 트랜잭션이 시작되기 전에 메서드를 재시도할 것입니다. 따라서, 재시도가 발생할 때마다 새로운 트랜잭션이 시작되고, 그 트랜잭션 내에서 메서드가 실행됩니다.
차이점 정리:
- 첫 번째 코드:
@Transactional
이 먼저 적용되므로 메서드가 트랜잭션 내에서 실행되고, 실패할 경우 롤백 후 재시도합니다. 각 재시도는 새로운 트랜잭션에서 실행됩니다. - 두 번째 코드:
@Retryable
이 먼저 적용되므로 재시도 로직이 트랜잭션 시작 전에 적용됩니다. 따라서, 각 재시도는 트랜잭션을 시작하기 전에 이루어지며, 새로운 트랜잭션에서 메서드가 실행됩니다.
이로 인해 두 코드 간에 재시도 시점과 트랜잭션 경계에서의 차이가 발생합니다. 일반적으로 재시도 로직이 먼저 적용되는 두 번째 코드가 더 많이 사용되며, 이는 재시도 로직이 트랜잭션 관리와 독립적으로 작동하게 합니다.
결론
저의 케이스에서는 결론적으로 첫 번째 코드 를 적용하여 중복 시 익셉션을 발생시켜 우선 롤백을 하고 재시도할 수 있도록 적용하였습니다.