-
Notifications
You must be signed in to change notification settings - Fork 28
[4주차] 비관적 락, 낙관적 락, 분산락 구현 #78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: strangehoon
Are you sure you want to change the base?
Conversation
|
@strangehoon 안녕하세요. 리뷰 시작하겠습니다. |
|
| MovieController.class, | ||
| ReservationController.class | ||
| }) | ||
| public abstract class IntegrationControllerSupport { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
추상 클래스를 통해 관리하신 부분 좋습니다 👍
| public class ReservationResponse { | ||
| private final Long userId; | ||
| private final Long screeningId; | ||
| private final List<Long> reservedSeatIds; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
필수 정보들 모두 포함시켜 주셨네요 좋습니다 💯
|
|
||
| // 1. 해당 상영 시간표에서 이미 예약한 좌석 수 확인 | ||
| int alreadyReservedCount = reservationRepository.countByUserIdAndScreeningId(request.getMemberId(), request.getScreeningId()); | ||
| int alreadyReservedCount = reservationRepository.countByUserIdAndScreeningId(request.getUserId(), request.getScreeningId()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
아래의 예외들의 경우, 무조건 IllegalArgumentException 이라기 보다는
비즈니스 정책 상의 예외라면, 무조건 400으로 떨어지는 예외 외에도 명확한 의미를 전달해줄 수 있는 InvalidFormatException 등의 이름을 활용해봐도 좋을 듯 합니다.
| @Aspect | ||
| @Component | ||
| @RequiredArgsConstructor | ||
| public class DistributedMultiLockAspect { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
요런 건 application 계층을 하나 만들어둬도 좋을 것 같아요.
domain 에 너무 많은 책임이 들어가있는 느낌이 듭니다.
| public void handle(ReservationCompletedEvent event) { | ||
| String message = "회원 %s님, 좌석 %d개 예약이 완료되었습니다." | ||
| .formatted(event.getUserName(), event.getSeatCount()); | ||
| messageService.send(message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
비동기로 메일 보내는 로직까지 구현해주셨네요 좋습니다 :)
| reservationValidator.validate(request); | ||
|
|
||
| User user = userRepository.findById(request.getUserId()) | ||
| .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다.")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UserNotFound 라는 예외를 던져도 좋겠네요 :)
|
|
||
| @Getter | ||
| @Builder | ||
| public class ReservationCompletedEvent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
request 패키지 내에 두신 이유가 있을까요?
event 라는 패키지를 만들어도 될거같네요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
따로 event 패키지 만드는게 좋아보이네요 ㅎㅎ
|
|
||
| @Configuration | ||
| @EnableAsync | ||
| public class AsyncConfig { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
디폴트 설정만 사용하기 보다는, 실제로 어떤 설정이 되는지 고민해보시고, 커스텀도 해보시면 좋습니다.
쓰레드 개수 설정도 해보시고요 :)
|
고생하셨습니다 👍 좋았던 점
아쉬웠던 점
질문에 대한 답변
|
|
리뷰 감사합니다!! 관련해서 리팩토링 해보겠습니다. 고생하셨습니다!! |
[4주차] 비관적 락, 낙관적 락, 분산락 구현
📝작업 내용
지난주 3주차에서 마무리하지 못했던 부분을 보완했습니다.
🔒해결하려는 문제 혹은 고민이 되었던 부분을 남겨주세요.(문제 수 만큼 복사해서 사용할 것)
지난주에는 INSERT 쿼리에 대한 동시성 제어 방식을 고려했지만, 그보다는 미리 screening 테이블에 좌석 데이터를 생성해두고, isReserved 컬럼을 통해 예약 여부를 판단하는 방식이 더 적절하다고 판단했습니다.
screeningId = 1일 때 userA가 seatId={1,2,3}을, userB가 seatId={3,4,5}를 동시에 요청하는 상황에서는 단순히 seatId에만 락을 걸 경우 충돌을 제대로 제어할 수 없습니다.
따라서, screeningId와 seatIds 조합에 대해 분산락을 걸 수 있도록 Redisson의 Multi Lock을 활용해 동시성을 제어했습니다.
기타 사항 📌
기능이 추가될 때마다 해당 기능이 어떤 모듈에 위치하는 것이 적절할지 판단하기 애매한 부분들이 있었습니다. 코치님께서 보시기에 구조상 어색한 부분이 있다면 한 번 확인해주시면 감사하겠습니다.
부하 테스트 결과, AOP 방식의 평균 응답 시간은 약 31.25ms, 함수형 방식은 약 33ms로 두 방식 간 큰 성능 차이는 나타나지 않았습니다. (VUs: 30, Duration: 30분)
lease time, wait time 설정 기준