-
mysql을 활용한 동시성 문제 해결 - 3. Named Lock백엔드 관련 강의 공부/동시성 이슈 - 재고시스템 2024. 2. 3. 16:55
3. Named Lock
이름을 가진 meta data lock이다. 이름을 가진 lock을 획득하고 해제할 때까지 다른 session은 이 lock을 획득할 수 없다.
트랜잭션이 종료될 때 자동으로 lock이 해제되지 않기 때문에 별도의 명령어로 해제해야만 한다.
public interface LockRepository extends JpaRepository<Stock, Long> { // 편의를 위해서 Stock 엔티티를 사용하는데, 실무에서는 data source를 분리해서 사용해야 한다. // 같은 data source를 사용하면 connection pool이 부족해진다. @Query(value = "select get_lock(:key, 3000)", nativeQuery = true) void getLock(String key); @Query(value = "select release_lock(:key)", nativeQuery = true) void releaseLock(String key); }
LockRepository를 별도로 만들었다. 실무에서는 이렇게 하면 안되고 별도의 JDBC 등을 사용해야 한다고 한다.
실제 로직 전, 후로 lock 획득, 해제를 해야하기 때문에 facade class를 추가해준다.
NamedLockStockFacade.class
@Component @RequiredArgsConstructor public class NamedLockStockFacade { private final LockRepository lockRepository; private final StockService stockService; @Transactional public void decrease(Long id, Long quantity) { try { lockRepository.getLock(id.toString()); stockService.decrease(id, quantity); } finally { lockRepository.releaseLock(id.toString()); } } }
StockService.class
@Service @RequiredArgsConstructor public class StockService { private final StockRepository stockRepository; @Transactional(propagation = Propagation.REQUIRES_NEW) public void decrease(Long id, Long quantity) { Stock stock = stockRepository.findById(id).orElseThrow(); stock.decrease(quantity); stockRepository.save(stock); } }
StockService를 사용하기 때문에 @Transactional 어노테이션에 propagation을 붙여준다.
이렇게 변경하고 테스트 코드를 실행해도 정상적으로 성공한다.
장점
Named lock은 주로 분산 lock을 구현할 때 사용한다. Named lock은 time out을 손쉽게 구현할 수 있다는 장점이 있다.
단점
트랜잭션 종료 시에 lock 해제, session 관리를 잘 해줘야하며, 실무에서 구현 방법이 다소 복잡할 수 있다.
'백엔드 관련 강의 공부 > 동시성 이슈 - 재고시스템' 카테고리의 다른 글
redis를 활용한 동시성 문제 해결 - 2. Redisson (0) 2024.02.04 redis를 활용한 동시성 문제 해결 - 1. Lettuce (0) 2024.02.04 mysql을 활용한 동시성 문제 해결 - 2. Optimistic Lock (0) 2024.02.03 mysql을 활용한 동시성 문제 해결 - 1. Pessimistic Lock (0) 2024.02.03 재고 시스템에서 동시성 문제 (0) 2024.02.03