HeartCount Asynchronous Issue
좋아요 개수 비동기 문제
상황 및 문제
코드
@Transactional
public void increment(CommentId commentId) {
Optional<CommentHeartCount> heartCount = repository.findByCommentId(commentId);
if (heartCount.isPresent()) {
heartCount.get().increment();
} else {
repository.save(new CommentHeartCount(CommentHeartCountIdFactory.newId(), commentId, START_INDEX));
}
}테스트 코드
@DisplayName("댓글 하트 카운트를 비동기로 증가시키면 증가시키는 개수만큼 증가한다")
@Test
void increment() throws InterruptedException {
// given
CommentId commentId = new CommentId("1");
CommentHeartCountId commentHeartCountId = CommentHeartCountIdFactory.newId();
commentHeartCountJpaRepository.save(new CommentHeartCount(commentHeartCountId, commentId, 1L));
CountDownLatch latch = new CountDownLatch(100);
AtomicInteger count = new AtomicInteger(1);
// when
for (int i = 0; i < 100; i++) {
threadPoolExecutor.execute(() -> {
latch.countDown();
commentHeartCountWriteService.increment(commentId);
count.incrementAndGet();
});
}
threadPoolExecutor.awaitTermination(1000, TimeUnit.MILLISECONDS);
// then
Optional<CommentHeartCount> heartCount = commentHeartCountJpaRepository.findByCommentId(commentId);
assertThat(heartCount).isPresent();
assertThat(heartCount.get().getCount()).isEqualTo(count.get());
}해결 방법
JPA 락 (Java Persistence API Lock)
낙관적 락 (Optimistic Lock):
비관적 락 (Pessimistic Lock):
@Transactional (스프링의 트랜잭션 관리):
데이터를 먼저 조회하지 않고, 직접 업데이트 쿼리를 실행
나의 선택
Last updated