ssung_항해일지/항해99_실전 프로젝트

실전 프로젝트 - 28일차

ssungcohol 2023. 4. 7. 21:58

동시성 문제를 해결하는 다양한 방법


Java 사용하는 방법

  • Synchronized를 활용한 방법
@Service
@RequiredArgsConstructor
public class StockService {

    private final StockRepository stockRepository;
    
    public synchronized void decrease(Long id, Long quantity) {
        Stock stock = stockRepository.findById(id).orElseThrow();
        stock.decrease(quantity);
        stockRepository.saveAndFlush(stock);
    }
  • 자바에서 지원하는, synchronized를 사용하면 접근하고 있는 메서드에 하나의 스레드만 접근할 수 있도록 작동
  • 현재 데이터를 사용하고 있는 해당 스레드를 제외하고 나머지 스레드들은 데이터 접근을 막아 순차적으로 데이터에 접근할 수 있도록 해줌

간단하게 메서드에 synchronized 키워드를 추가하고, @Transactional을 제거함으로써 동시성 문제를 해결할 수 있다.

Transactioanal을 제거하는 이유는 트랜잭션 관리 방식은 기본적으로 프록시 방식으로 AOP가 적용되기 때문.
트랜잭션 프록시가 트랜잭션 처리 로직을 수행할 때 새로운 클래스를 만들어 Logic을 실행하게 된다.
synchronized를 통해 한 개의 스레드만 접근할 수 있게 막더라도 트랜잭션에 의해 새로운 프록시로 수행하게 되어버리면 프록시 로직은 synchronized가 걸린 상태가 아니기 때문에 원하는 결과를 얻지 못함

  • 문제점
    • Synchronized는 하나의 프로세스 안에서만 보장이 된다
    • 즉, 서버가 1대일 때는 문제가 없지만 서버가 여러 대 일경우 인스턴스가 여러 개 존재하는 것이기에, 실질적인 운영 환경에서는 데이터의 정합성을 보장할 수 없음

DB 사용하는 방법

  • Pessimistic Lock (비관적 락)
    • 트랜잭션이 시작될 때 Shared Lock 또는 Exclusice Lock을 걸고 시작하는 방법
    • Shared Lock을 걸게 되면 write를 하기 위해서는 Exclucive Lock을 얻어야하는데 Shared Lock이 다른 트랜잭션에 의해 걸려있으면 해당 Lock을 얻지 못해 업데이트를 할 수 없음
    • 수정하기 위해서는 해당 트랜잭션을 제외한 모든 트랜잭션이 종료(commit) 되어야한다.
  • Optimistic Lock (낙관적 락)
    • Optimistic Lock은 수정할 때 먼저 이 값을 수정했다고 명시하여 다른 사람이 동일한 조건으로 값을 수정할 수 없게 하는 것.
    • 낙관적 락은 DB에서 제공해주는 특징을 이용하는 것이 아닌 Application Level에서 잡아주는 Lock
    • 낙관적 락은 별도의 version 구분 컬럼을 추가하여 충돌적인 업데이트를 막아줌
    • version 뿐만 아니라 hashcode 또는 timestamp를 사용하기도 한다.
  • Rollback (롤백)
    • 업데이트를 하는 테이블이 1개가 아니라 2개의 테이블이며 2번째 테이블을 업데이트하다 이와같은 충돌이 발생했다면 하나의 수정 요청에 대해서는 롤백이 필요
    • 비관적 락은 하나의 트랜잭션으로 묶여있기 때문에 수정이 하나 실패하면 DB 단에서 전체 Rollback이 발생
      • 만약 실패시에는 Transaction이 실패한 것이기에 트랜잭션 전체에 자동으로 rollback 발생
    • 낙관적 락은 트랜잭션을 사용하지 않기에 충돌이 발생하여 수정을 못한 부분이 있으면 롤백에 대한 책임을 Application 단에서 가지고 Application에서 수동으로 롤백을 해줘야 한다.
  • 비관적 락 vs 낙관적 락
    • 성능적으로는 비관적 락이 더 좋다. 
    • 낙관적 락은 트랜잭션이 필요하지 않다.
    • 낙관적 락의 최대 단점 = 롤백이다. => 충돌 발생 시 개발자가 수동으로 롤백을 하나하나 처리해줘야 한다.
    • 비관적 락은 트랜잭션을 롤백하면 끝남
    • 따라서, 낙관적 락은 충돌이 많이 예상되거나 충돌이 발생했을 때 비용이 많이 들것이라고 판단되는 곳에서는 사용하지 않는 것이 좋아보임
728x90