[프로젝트] 동시성 테스트를 해봤다-2(초안)

Godtaek·2024년 2월 12일
0

project

목록 보기
3/4

1. synchronized 키워드

@Override
@Transactional
public synchronized void pay(Long userId, Long itemId) {

SalesItemEntity item = entityManager.find(SalesItemEntity.class, itemId);

if (item.getStock() < 1) {
     throw new AlcoholException(ErrorCode.NO_SUCH_ITEM, String.format("%s님의 주문이 실패했습니다. 재고가 부족합니다.", userId));
}

item.setStock(item.getStock()-1);
entityManager.merge(item);
}

평균시간 : 35~38초
API 호출 : item used: {1: 1027, 2: 984, 3: 1017, 4: 1002, 5: 996, 6: 998, 7: 969, 8: 1005, 9: 1010, 10: 992}

재고 수

생각보다 동시성 이 잘 지켜지진 않는 모습

2. 비관적 락

SalesItemEntity item = entityManager.find(SalesItemEntity.class, itemId, LockModeType.PESSIMISTIC_WRITE);

if (item.getStock() < 1) {
    throw new AlcoholException(ErrorCode.NO_SUCH_ITEM, String.format("%s님의 주문이 실패했습니다. 재고가 부족합니다.", userId));
}

item.setStock(item.getStock()-1);
entityManager.merge(item);

를 사용한다.

평균시간 : 30~38초
에러 수: 115개
사용 item: {1: 1000, 2: 1000, 3: 1000, 4: 1000, 5: 989, 6: 957, 7: 972, 8: 1000, 9: 1000, 10: 967}

동시성 보장이 잘 된 것을 볼 수 있다. 사실 성능 차이는 크게 없어 보인다.

3. 낙관적인 락

사실 낙관적인 상황이 아니라(데이터가 반드시 충돌하는 상황) 낙관적인 락이 어울리진 않는다.

// entity에 버전을 추가해준다.

@Version
private int version;

평균시간: 35~45초
비관적인 락보다 시간 효율이 높게 예상했지만, 충돌이 자주 발생하면서 더 많은 시간이 걸린 듯하다.
에러 수: 다양한데 이번 케이스에선 3499번
호출한 상품 수 : {1: 699, 2: 631, 3: 651, 4: 661, 5: 631, 6: 653, 7: 655, 8: 605, 9: 647, 10: 668}

그 와중에 동시성은 잘 지켜졌다.

4. Redis

별도의 동시성 처리를 하지 않고, Redis만 써봤다.

평균시간 : 25초대
에러수 : 0
호출한 상품수 : {1: 1004, 2: 1001, 3: 956, 4: 975, 5: 1019, 6: 1005, 7: 999, 8: 1010, 9: 1015, 10: 1016}

별도의 처리를 하지 않고는 동시성이 지켜지진 않는다. Redis 자체의 성능이 RDBMS보단 뛰어나기 때문에 비교적 많은 요청을 잘 처리한 것 같다.

profile
성장하는 개발자가 되겠습니다

0개의 댓글