

어플리케이션을 만들다보면 동시성 이슈는 항상이 일어난다.
예를들어 100개의 물건이 있을때 한사람당 하나씩 구매를 한다고 가정해 보자. 예상대로라면 한사람당 하나씩 가져가므로 100개의 요청을 동시에 보내면 정상동작 할것 같지만 그렇지 않다. a라는 유저가 구매후 차감된 데이터가 업데이트 되기전 b유저가 구매할수도 있는등등(정합성) 여러 문제들이 일어난다.
- synchronized
- pesmistic lock(비관적락)
- optimistic lock(낙관적락)
- named lock
- redis lettuce
- redisson




트랜잭션 빼고 synchronized만 구현했을경우

트랜잭션 + synchronized
이 경우 트랜잭션이 끝나기전에 다른 스레드가 자원에 접근하기 떄문에 테스트가 실패한다.
synchronized 한개의 쓰레드만 접근 가능하며 각 프로세스 안에서만 보장, 즉 여러 서버에서 동시에 접근하면 레이스 컨디션이 발생한다.




비관적 락은 데이터베이스 레벨에서 락을 걸어 다른 트랜잭션이나 스레드의 접근을 제한
다른 접근을 제한함으로써 데이터의 정합성은 높지만 그만큼 성능 저하가 발생함



optimistic Lock은 버전으로 상태를 모니터링 한다.
예를들어 a 트랜잭션에서 데이터를 변경하고 버전 1에서 버전2로 바꾸고 그 과정에 동시접근한 b트랜잭션에서도 데이터를 변경하고 트랜잭션 종료할때 b트랜잭션의 버전은 아직 1이므로 버전 불일치로 예외가 발생한다.





트랜잭션에 옵션을 안주고 decrease 메서드에서 에러가 발생하면 락을 해제 못하는 문제 발생!(트랜잭션이 끝난다해도 락해제가 안돼기 때문)
그래서 부모의 트랜잭션과 별도로 실행하도록 트랜잭션에 옵션을 설정해준다(기존 트랜잭션과 완전분리)





처음에는 키가 1인 데이터가 없어서 성공

그 뒤로는 데이터가 있으니 실패한다
이 원리를 이용해보자







락해체가 되엇다고 알려주고 그제서야 락획득을 시도하기떄문에 한번 혹은 몇번만더 실행함으로써 레디스의 부하를 줄여준다
락관련 클래스들을 라이브러리에서 제공 함으로 따로 레포지토리를 만들지 않아도 괜찮다.