인프런 커뮤니티 질문&답변

요니님의 프로필 이미지
요니

작성한 질문수

재고시스템으로 알아보는 동시성이슈 해결방법

Pessimistic Lock 활용해보기

PessimisticLock을 분산락으로 활용하는 질문에 대한 답변 남기겠습니다.

작성

·

173

0

github repository url
: https://github.com/developer-yoni/ecommerce/tree/study/concurrency/redis

여기서 study/concurrency/redis 브랜치를 확인해주시면 됩니다.
StockServiceTest의 400번째 라인부터 503번째 라인까지
테스트 코드가 작성되어 있습니다.
큰 흐름은 동시성 이슈가 발생가능한 Stock에는 Lock을 걸지 않고,
다른 Entity인 Market Entity에 PessimisticLock을 걸어,
PessimisticLock을 분산락으로 활용하려는 시도 입니다.

여기서 4_1 테스트는 Market에 PessimisticLock을 거는 트랜잭션과 Stock의 재고를 감소시키는 트랜잭션을 하나의 트랜잭션으로 묶었고,
4_2 테스트는 별개의 트랜잭션으로 분리했습니다.

이때 질문은 다음과 같습니다
Q1. 동시성 이슈가 일어나지 않는 다른 Entity에 PessimisticLock을
걸어 분산락처럼 활용하는게 문제가 되지 않을지 궁금합니다.

혹시 문제가 된다면 , 어떤 측면에서 문제가 될지 궁금합니다.
왜냐하면 어차피 동시성 이슈가 일어날 수 있는 측면의 값을 커밋하여 update함과 동시에
PessmisticLock을 반환하는 것이니 문제가 되지 않을것이라고 생각했기 때문입니다.

Q2. PessimisticLock을 건 트랜잭션이 커밋되거나 롤백될 때 비로소 PessmisticLock이 반환된다는 점을 근거로,
4_2 테스트에서는 일부로 재고감소를 먼저 커밋한 후,
Market의 PessimisticLock을 커밋하여,
반드시 업데이트가 이뤄난 후 락을 반환하는것을 의도하였습니다.

그러나 제 의도와 다르게 4_2 테스트는 계속 lock이 걸려있는?
흐름을 보이면서 테스트에 실패합니다.
그원인을 잘 모르겠습니다.


바쁘신 와중에 답변 달아주셔서 감사합니다 강사님.

 

답변 2

0

최상용님의 프로필 이미지
최상용
지식공유자

요니님 안녕하세요.
프로젝트의 규모가 생각보다 큰듯하여 파악을 먼저해본 후 답변을 다시 남기도록 하겠습니다.

감사합니다.

0

안녕하세요, 인프런 AI 인턴입니다.

요니님 질문에 답변 드리겠습니다.

Q1에 대하여:
PessimisticLock을 다른 Entity에 걸어 분산락으로 활용하는 것은 기술적으로 가능하겠으나, 설계상 몇 가지 고려해야 할 문제가 있습니다. 첫째, 동시성 이슈가 없는 Entity에 락을 건다면, 그 Entity의 처리가 병목이 되어 전체 시스템의 성능에 영향을 줄 수 있습니다. 두 번째로는 의도하지 않은 Deadlock 발생 가능성입니다. 트랜잭션이 다른 락을 기다리는 동안 발생할 수 있는 문제로, 복잡한 시스템에서 디버깅 및 유지보수를 어렵게 만듭니다. 또한, 분산 시스템의 경우 락을 걸고 관리하는 로직이 더욱 복잡하고 JPA가 지원하는 락 방법은 데이터베이스 세션에 국한되므로, 여러 데이터베이스 세션 또는 애플리케이션 인스턴스를 걸쳐 분산락을 유지 관리하기에는 적합하지 않을 수 있습니다.

Q2에 대하여:
트랜잭션이 커밋되거나 롤백될 때만 락이 반환되기 때문에 우선적으로 커밋을 해도, 해당 트랜잭션 내에서 락이 사용되는 로직이 완전히 완료되지 않으면 락이 해제되지 않을 수 있습니다. 테스트 실패의 원인은 락이 적절히 해제되지 않거나 코드 내의 다른 로직이 원하는 흐름으로 진행되지 않기 때문일 수 있습니다. 로그를 확인하거나 디버거를 사용해서 트랜잭션의 흐름을 단계별로 확인하여 문제를 진단하는 것이 필요합니다. 또한, 록이 설정되는 순서나 다른 트랜잭션이 락을 기다리는 방식에서 예상치 못한 문제가 발생하고 있을 가능성도 있습니다.

세세한 부분까지 살펴야 하는 문제이므로 Spring Data JDBC의 @Lock 어노테이션을 사용하는 방법이나 Spring Data JPA의 @Lock 사용 예제를 참고하시어 문제를 해결하는 데 도움이 될 수 있을 것입니다.

Spring Data JDBC - Reference Documentation v3.1.5의 JDBC Locking 절에서는 다음과 같이 설명하고 있습니다.
참고 문서

interface UserRepository extends CrudRepository<User, Long> {

@Lock(LockMode.PESSIMISTIC_READ)
List<User> findByLastname(String lastname);
}

그리고 Spring Data JPA의 Locking 절에서 제공된 예제는 다음과 같습니다.
참고 문서

interface UserRepository extends Repository<User, Long> {

@Lock(LockModeType.READ)
List<User> findByLastname(String lastname);
}

문서를 잘 살펴보시고 테스트 코드의 상황에 맞게 적용하시면 문제 해결에 도움이 될 것입니다.

감사합니다.

요니님의 프로필 이미지
요니

작성한 질문수

질문하기