낙관적 Lock을 통한 처리 시나리오

Terror·2024년 10월 30일

최종 프로젝트

목록 보기
10/28

Overivew

  • 지난시간 에는 Jmeter를 활용한 여러개의 서버에서 한가지의 리소스에 대해서 접근하는 테스트를 해보았고, 에러도 적절하게 반환됨을 파악하였다
  • 혹시 낙관적락에 대한 예외처리가 궁금하신 분은 이곳을 참고하기 바란다
  • 낙관적락 처리를 통한 예외처리가 가능합니다

시나리오

  • 1명의 유저는 1개의 포트폴리오를 가지고있다
  • 1개의 회사는 1개의 외주(공고)를 올릴 수 있다
  • 1명의 유저는 1개의 포트폴리오를 가지고, 1개의 외주에 신청(매칭) 할 수 있다
  • 1개의 회사에서는 여러명의 담당자가 있을 수 있고, 여러명의 담당자는 1개의 신청(매칭)에 대해 수락,거절을 누를 수 있다

낙관적 Lock을 처리하기전

    @Transactional
    @Override
    public ApiResponse<Void> updateMatching(Long matchingId, MatchingRequest.MatchingRequestUpdate updateReqDto, AuthUser authUser) {
        MatchingValidator.isNotCompany(authUser);
        Matching findMatching = findById(matchingId);
        findMatching.statusChange(updateReqDto.status());
        return ApiResponse.of(MATHCING_SUCCESS);
    }
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@DynamicUpdate
@Builder
@Entity
public class Matching extends Timestamped {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "portfolio_id")
    private Portfolio portfolio;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "outsourcing_id")
    private Outsourcing outsourcing;

    // 지역
    @Enumerated(value = EnumType.STRING)
    private MathingStatusType status;

    public Matching(User user, Portfolio portfolio, Outsourcing outsourcing, MathingStatusType status) {
        this.user = user;
        this.portfolio = portfolio;
        this.outsourcing = outsourcing;
        this.status = status;
    }

    public void statusChange(MathingStatusType status){
        this.status = status;
    }
}

100명의 담당자가 하나의 매칭에 대해 수락하는 시나리오


  • 예상
    1. 동시성 처리에 대한 부분이 따로 존재하지않기 때문에 예외같은 부분이 발생되지않고 전부 정상적으로 실행될것이다

  • 역시 아무런 문제없이 저장됐고, DB에도 정상적으로 들어가있음을 파악 할 수 있다

낙관적락 처리후

    @Transactional
    @Override
    public ApiResponse<Void> updateMatching(Long matchingId, MatchingRequest.MatchingRequestUpdate updateReqDto, AuthUser authUser) {
        try {
            MatchingValidator.isNotCompany(authUser);
            Matching findMatching = findById(matchingId);
            findMatching.statusChange(updateReqDto.status());
            matchingRepository.flush();
            return ApiResponse.of(MATHCING_SUCCESS);
        } catch (OptimisticLockingFailureException e) {
            throw new MatchingException(MATCHING_LOCK);
        }
    }
  • Mathcing Entity에 @Version 칼럼 하나 추가해주었다

100명의 담당자가 하나의 매칭에 대해 수락하는 시나리오

  • 상단과 동일하게 진행하였다
  • 여러개의 쓰레드가 동일하게 version1에 대한 데이터를 건들고, 다른 쓰레드가 먼저 데이터를 업데이트 시켜버리면 version2가 되면서 version1에 대한 데이터를 수정하고 flush()가 되는시점에 오류가 발생되는 원리이다
  • 우리가 예외처리한 부분이 제대로 적용됨을 볼 수 있다

마치며

  • 낙관적락을 통한 동시성제어의 방법을 알아보았다
  • 상단의 시나리오로 예시를 들어보면, 3명의 담당자가 하나의 요청에 대해 수락 거절 수락을 누르면, 3개의 쓰레드가 동시에 서버에 접근하게되고 3개의 요청중 하나가 먼저 처리되면 다른 2개의 쓰레드는 version1에 대한 데이터를 수정하기 때문에 예외가 발생될것이고, 그에대한 예외처리문구를 그 담당자들에게 전해주는 흐름이다

끝!

profile
테러대응전문가

0개의 댓글