1. Lock 옵션에 따른 실험 결과
1)Lock 옵션 종류와 설명
ㄱ. Optimistic
- NONE : 별도의 옵션을 사용하지 않아도 Entity에 @Version이 적용된 필드만 있으면 낙관적 잠금이 적용됩니다.
- OPTIMISTIC(read) : Entity 수정시에만 발생하는 낙관적 잠금이 읽기 시에도 발생하도록 설정합니다.
읽기시에도 버전을 체크하고 트랜잭션이 종료될 때까지 다른 트랜잭션에서 변경하지 않음을 보장합니다.- 이를 통해 diry read와 non-repeatable read를 방지
- OPTIMISTIC_FORCE_INCREMENT(write) : 낙관적 잠금을 사용하면서 버전 정보를 강제로 증가시키는 옵션
ㄴ. Pessimistic
- PESSIMISTIC_READ : dirty read가 발생하지 않을 때마다 공유 잠금(Shared Lock)을 획득하고 데이터가 UPDATE, DELETE 되는 것을 방지 할 수 있습니다.
- PESSIMISTIC_WRITE : 배타적 잠금(Exclusive Lock)을 획득하고 데이터를 다른 트랜잭션에서 READ, UPDATE, DELETE 하는것을 방지 할 수 있습니다.
- PESSIMISTIC_FORCE_INCREMENT : 이 잠금은 PESSIMISTIC_WRITE와 유사하게 작동 하지만 @Version이 지정된 Entity와 협력하기 위해 도입되어 PESSIMISTIC_FORCE_INCREMENT 잠금을 획득할 시 버전이 업데이트 됩니다.
2)실험 결과 요약
- 현재 서비스에서는 PESSIMISTIC_WRITE만 제대로 작동한다.
- Optimistic은 성능은 좋지만 주문이 폭주하는 경우 트랜잭션을 시작할 때 저장한 버전 값과 트랜잭션이 끝나고 난 후 체크한 버전값이 다른 경우가 많은데 이 때 잘 작동하지 않는다. 따라서 진행하는 서비스에는 적합하지 않다.
- 또한 Force_Increment 옵션의 경우 지원하는 DB의 종류가 정해져있는데, 현재 사용중인 mysql에서는 사용이 불가능하다.
- PESSIMISTIC_READ는 어떤 트랜잭션이 수정중일 때 다른 트랜잭션에서 읽기는 가능하다. 하지만 현재 실험에서는 모든 트랜잭션들이 수정하고자 하기 때문에 적합하지 않다.
- PESSIMISTIC_WRITE를 사용한 결과
2. Redisson Distribution Lock
- Transaction이 Lock을 점거하고 있다는 정보를 redis 서버(캐시 서버)에 올려서, 분산된 서버에서 하나의 DB를 조회하고 수정할 때 사용하기에 적절한 방법이다.
- 아래 자세히 설명하겠지만, 요청 Thread를 순서대로 처리한다는 보장이 없다는 단점이 있다.
1)실험 결과 요약
- 잘 작동하지만 아래와 같이 주문 id가 순서대로 되어있지 않다. 즉 요청된 Thread를 순서대로 처리하지 않는다.
- 이러한 단점을 해결하기 위해선 Redisson Distribution Lock 이 아니라 Redisson Fair Lock을 사용해한다.
- 하지만 이 경우에는 DeadLock 문제가 발생할 가능성이 있다.
- 순서대로 처리하지 않는 이유는 먼저 Thread가 lock을 선점한 동안 여러개의 Thread가 대기중일 때, 먼저 선점한 Thread가 트랜잭션을 완료 한 이후 어떤 Thread가 lock을 점유할지 모르기 때문이다.
- Thread1번이 3초가 걸리는 Transaction을 진행중이다.
- 이때 Thread 2번 부터 10번까지 대기를 한다.
- 2~10번까지 Thread1 이 끝날때 까지 계속 lock 점거를 요청한다.
- 2~10번이 계속 요청하기 때문에 1번 종료 시점에 누가 점유하게 될지 장담할 수 없다.
3. 참조
1)mysql 데이터 테이블 기반 테스트 코드 작성하기 : https://dev-coco.tistory.com/85
2)LockModeType : https://velog.io/@lsb156/JPA-Optimistic-Lock-Pessimistic-Lock
3)Redisson분산락 : https://velog.io/@hgs-study/redisson-distributed-lock