• 재고시스템으로 알아보는 동시성이슈 해결방법 강의 노트

    2023. 3. 15.

    by. Sohyun

    아래는 재고시스템으로 알아보는 동시성이슈 해결방법 강의를 정리한 내용입니다.
    실제 강의에서는 예시를 통해 설명하고 있어 강의를 보는 것을 추천합니다.


    레이스컨디션이란

    두 개 이상의 프로세스가 공통 자원을 읽거나 쓸 때,
    접근 순서에 따라 실행결과가 달라지는 상황을 레이스 컨디션이라 한다.
     
    = 데이터의 안정성과 신뢰성을 보장할 수 없다.
     
     

    Synchronized 이용해 보기

    • 자바에서는 synchronized를 사용해서 하나의 스레드만 접근 가능하도록 할 수 있다.
    • 메서드에서 사용 또는 객체 변수에 사용
    • Sychronized는 하나의 프로세스 안에서만 보장이 된다.

    결론적으로 서버가 1대일 때에는 괜찮겠지만 여러 대가 되면 사용할 수 없음(운영에선 거의 사용되지 않음)
     
     

    Database 이용해 보기

    1. Pessimistic Lock

    • 실제로 데이터에 락을 걸어서 정합성을 맞춰주는 방법
    • exclusive lock 걸리면 락 해제되기 전까지는 다른 스레드에서 접근 불가
    • 쿼리문 + for update로 알 수 있음
    • 충돌이 빈번하게 일어난다면 Optimistic Lock보다 성능 좋을 수 있음
    • 락을 통해 제어하므로 정합성 어느 정도 보장된다는 장점,
    • 단점으로는 별도의 락을 잡으므로 성능감소가 있을 수 있다는 점

     
    2. Optimistic Lock

    • 락 이용하지 않고 버전 이용해서 정합성 맞추는 방법
    • 같은 버전에 업데이트 2개가 들어왔을 때, 앞사람이 바꾸고 버전 올려버리면 뒷사람은 바꾸지 못하는 식
    • 장점은 별도의 락을 잡지 않으므로 pessimistic lock보다 성능상 이점이 있음
    • 단점으로는 업데이트 실패 시 재시도 로직을 개발자가 만들어 주어야 함
    • 충돌이 빈번하게 일어날 확률이 높다면 pessimistic lock사용하는 것을 권장

     
    3. Named Lock

    • 이름을 가진 메타데이터 락
    • 이름을 가진 락을 획득 후 해제 될 때까지 다른 세션은 락 획득 못함
    • 트랜젝션 종료될 때 자동으로 락이 해제되지 않으므로 별도의 명령어 사용하거나 선점 시간 끝나야 해제됨

     

    Redis 이용해 보기

    1. Lettuce

    • spin Lock은 락 획득하려는 스래드가 획득가능한지 계속 확인하면서 획득하는 방식
    • mysql의 네임드락이랑 비슷함
    • 다른 점은 레디스 활용한다는 점이랑 세션관리에 신경 쓰지 않아도 된다는 점
    • key로 setnx 하여 락을 획득하고 완료 시 키를 삭제하여 락을 해제해 주는 방식
    • 구현이 간단하다는 장점
    • 단점은 스핀락 방식이므로 레디스에 부하를 줄 수 있음
    • 때문에 Thread.sleep을 통해서 락 획득기간에 텀을 주어야 함

     
    2. Redisson

    • 레디슨은 자신이 점유하고 있는 락을 해제할 때, 채널에 메시지를 보내줌으로 써 락 획득을 하라고 알려주몬 락 획득 시도함
    • 락 관련한 클래스 제공함
    • pub-sub : 채널을 하나 만들고 락을 점유 중인 스레드가 획득 대기 중인 스레드에게 해제를 알려주면 그때 시도하는 방식
    • 별개의 리트라이 로직을 작성하지 않아도 됨

     
     
    # 인프런 강의 추천 (내돈내산)
    [ 재고시스템으로 알아보는 동시성이슈 해결방법 ]


     
     

    결론

    어떤 데이터를 업데이트하는 로직을 생성했을 때 알아서 한 번에 하나의 스레드만 접근할 거라는 행복한 상상을 해서는 안된다.
    줄을 세워서 순차적으로 접근할 수 있도록 처리해주어야 한다.

    아니면 다른 방법이라도.. 🤔

     

    댓글