Skip to content

[5주차] 낙관적락 분산락 적용#104

Open
kimbro97 wants to merge 6 commits intohanghae-skillup:kimbro97from
kimbro97:kimbro97
Open

[5주차] 낙관적락 분산락 적용#104
kimbro97 wants to merge 6 commits intohanghae-skillup:kimbro97from
kimbro97:kimbro97

Conversation

@kimbro97
Copy link

@kimbro97 kimbro97 commented Feb 9, 2025

[5주차] 낙관적락 분산락 적용


작업 내용

  • Redis Lua script를 활용해 낙관적 락 구현
  • AOP 기반 분산락 구현
  • 함수 기반 분산락 구현

발생했던 문제와 해결 과정을 남겨 주세요.

이번 주차에서 고민되었던 지점이나, 어려웠던 점을 알려 주세요.

리뷰 포인트

  • 낙관락과 분산락을 잘 적용했는지 궁금합니다.
  • Redis 락을 설정할때 leaseTime, waitTime을 적절히 설정했는지 궁금합니다.

기타 질문

  • 실무에서는 최종적으로 분산락과 낙관락을 같이 사용한다고 들었는데 어떤 경우에 사용하는건지 궁금합니다.
  • 조회 API가 아닌 예매 API 같은경우는 어떤 기준으로 성능 측정을 하는지 궁금합니다.

@youngxpepp youngxpepp self-requested a review February 11, 2025 12:18
Copy link

@youngxpepp youngxpepp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

안녕하세요 형재님! 이건홍 코치입니다.
5주간 정말 고생하셨습니다. 앞으로 개발자로서의 길을 응원하겠습니다.
감사합니다 😄

좋았던 점

  • 분산락을 통해 예약에 대한 데이터 무결성을 지킴
  • 함수형 분산락을 구현해서 부분적인 critical section을 보호함

아쉬운 점

  • JPA의 낙관적 락이 사용됐으면 좋았을텐데 아쉽네요!

질의응답

  • Q. 실무에서는 최종적으로 분산락과 낙관락을 같이 사용한다고 들었는데 어떤 경우에 사용하는건지 궁금합니다.
    A. JPA의 낙관적락에 대해 찾아보시겠어요? 낙관적 락(Optimistic Locking)은 동시에 여러 트랜잭션이 같은 데이터를 수정하려고 할 때, 충돌이 없을 것이라고 가정하고 작업을 진행하는 방식입니다.
  • Q. 조회 API가 아닌 예매 API 같은경우는 어떤 기준으로 성능 측정을 하는지 궁금합니다.
    A. 많은 사용자가 한꺼번에 예약하려고 하는 티켓팅을 생각하시면 좋겠습니다. 얼마나 많은 사용자를 수용할 수 있는지가 관건이에요!


ReservationValidationResult validationResult = reservationValidate.validate(request);
List<String> lockKeys = request.getSeatIds().stream()
.map(seatId -> "reservation:screening:" + request.getScreeningId() + ":seat:" + seatId)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

키 생성하는 로직을 따로 메서드로 관리하는건 어때요?


return action.get();
} catch (InterruptedException e) {
throw new RuntimeException(e);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

InterruptedException은 어느 상황에 발생할까요?
해당 상황이 언제 발생하고 어떻게 대응해야 하는지 생각해보셨으면 좋겠어요.

Comment on lines +28 to +30
if (!allLocked) {
throw new IllegalArgumentException("해당 좌석은 현재 다른 사용자가 예매를 진행하고 있습니다.");
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

잠금에 대한 코드인데 좌석 예약에 대한 비지니스 로직이 들어가 있네요!?

Comment on lines +36 to +42
if (allLocked) {
locks.forEach(lock -> {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
});
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

쓴 자원은 꼭 반납해줘야 합니다👍 잘하셨어요

// @DistributedLock(key = "reservation:screening:{#request.screeningId}:seat:{#request.seatIds}", leaseTime = 2, waitTime = 2)
@Transactional
@DistributedLock(key = "reservation:screening:{#request.screeningId}:seat:{#request.seatIds}", leaseTime = 10, waitTime = 5)
public ReservationServiceResponse reserve(ReservationServiceRequest request) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

예약 메소드에서 좌석이 붙어 있는지 혹은 최대 3개인지 등등의 검증이 이루어졌으면 좋겠습니다!
사용자의 요청은 100% 신뢰할 수 없으니깐요.

Comment on lines +37 to +45
ReservationValidationResult validationResult = reservationValidate.validate(request);

Reservation reservation = createReservation(validationResult);
Reservation reservation = createReservation(validationResult);

reservationRepository.save(reservation);
reservationRepository.save(reservation);

messageService.send();
messageService.send();

return ReservationServiceResponse.of(reservation);
return ReservationServiceResponse.of(reservation);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

예약을 위해 redis에 특정 좌석이 예약이 되었는지 아닌지 저장하고 있는거 같아요! 관계형 데이터베이스에서 지원하는 낙관적 락을 사용하시는건 어때요? redis는 휘발성 데이터베이스이기 때문에 예약에 대한 정보를 저장하기에는 적합하지 않아 보입니다.

추가로, 형재님이 작성하신 코드의 흐름은 다음과 같아 보여요.

  1. 분산락을 통해 좌석 예약에 접근하는 사람은 한 사람이어야 함
  2. 예약이 되었는지 안되었는지 분산락을 통해 확인함
  3. 예약 성공

JPA에서 제공하는 @Version 어노테이션을 통한 낙관적 락을 사용해보시겠어요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants