@Transactional public CardStatusResponse updateCard(Long cardId, CardUpdateRequest cardUpdateRequest, User user) { Card card = getCardById(cardId); if(!user.getId().equals(card.getOwner().getId())) throw new IllegalArgumentException("해당 카드를 수정할 권한이 없습니다."); RLock lock = redissonClient.getFairLock("card:" + cardId); try{ if(lock.tryLock(10, 60, TimeUnit.SECONDS)){ try{ card.update(cardUpdateRequest); } finally { lock.unlock(); } } else{ throw new IllegalArgumentException("다른 유저가 이미 수정중입니다."); } } catch (InterruptedException e){ Thread.currentThread().interrupt(); } return new CardStatusResponse(201, "OK", card.getId()); }
Redisson
을 사용하여 카드 업데이트 함수에분산락
을 적용하였다.
@Test public void updateCardConcurrencyTest() throws InterruptedException{ User user = new User(1L); int numberOfThreads = 10; // 쓰레드 생성 ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads); // 주어진 수 만큼 이벤트를 기다림 CountDownLatch latch = new CountDownLatch(numberOfThreads); for (int i = 1; i <= numberOfThreads; i++) { // 각 쓰레드에서 사용할 요청 생성 CardUpdateRequest cardUpdateRequest = new CardUpdateRequest(1L, "Update Name " + i, "Update Description " + i, "Update Color " + i, "startDate", "endDate"); int finalI = i; executorService.submit(() -> { try { System.out.println(finalI + "번째 쓰레드 접근 시작"); cardService.updateCard(1L, cardUpdateRequest, user); } finally { latch.countDown(); System.out.println(finalI + "번째 쓰레드 접근 종료"); } }); } latch.await(); // 모든 쓰레드의 작업이 완료될 때까지 대기 executorService.shutdown(); }
- 10개의
쓰레드
에서 동시에 카드를 수정하도록 테스트 코드를 구현하였다.
- 쓰레드들이 순차적으로 접근하면서 테스트가 잘 수행되었다.
- 하지만 문제가 있다.
- 테스트가 끝나면 DB에 테스트 결과가 남아버린다.
- 그래서 매번 테스트를 다시 진행할때 마다 Drop Table을 했었다.
- H2 Database는 자바로 작성된 관계형 데이터베이스 관리 시스템이다.
- 특징으로는
In-Memory
데이터베이스이기 때문에 실행할때마다 초기화된다!
- H2의 적용법은 간단하다.
- application.properties에 연결해주고, 의존성 추가만 해주면 끝이다!
- 평소에는
MySQL
로 작동하지만 테스트를 진행할때는H2
로 작동하게 하려고 한다.- 테스트용 환경을 따로 구축하기 위해서는 test 디렉토리에 application.properties를 따로 만들어주면 test할때만 적용된다!
- 테스트용 application.properties만 만들어주면 적용은 끝이다!
- 테스트는 이전과 동일하게 동작하지만
MySQL
이 아닌H2
로 동작하기에 DB에 아무것도 남지 않는다.
사실 분산락을 통해 동시성 제어하는 기능을 구현하였지만
이번 프로젝트에는 딱히 동시성을 제어할 부분이 없었다.
그래도 이제는 할줄 안다는것에 의미를 두려고 한다!