Skip to content

2차: Skip Locked 기반 락 병목 해결

김현준 edited this page Sep 3, 2024 · 2 revisions

🔍 문제 분석

문제 상황 이해

ERD

문제 상황의 ERD

배경 설명

  • 하나의 축제(festival)은 여러 개의 티켓(ticket) 종류를 가짐 (OneToMany)
    • 예를 들면 티켓도 혜택 종류에 따라 가격이 다른 티켓을 가질 수 있다는 상황을 가정
  • 티켓(ticket)은 하나의 티켓 재고(ticket_stock)를 가짐 (OneToOne)
    • 실질적인 티켓 재고는 remain_ticket_stock에서 int로 하나씩 차감하는 형태로 관리가 됨
    • 하나의 컬럼으로 관리
  • 선착순 로직 상 동시 예매가 일어날 것이 분명했고 이에 따라 낙관적 락보다는 비관적 락을 이용해 재고에 대해 Exclusive Lock을 걸어 동시성 문제를 해결했음

문제 상황 설명

  • 문제는 재고를 하나의 컬럼으로 관리 했기 때문에 아래의 그림과 같이 락이 걸리게 되면 그 락이 풀릴 때까지 모든 락이 기다리게 되었음
Lock Situation
  • 위의 문제로 락을 기다리는 커넥션이 늘고, 커넥션의 응답을 기다리는 쓰레드가 많아짐
  • 커넥션 풀과 쓰레드 풀에서 병목 현상이 발생함

🛠️ 해결 방안

아이디어

  1. 분산락 사용
    1. 데이터베이스 수준이 아닌 애플리케이션 수준에서 제어하는 방법
    2. 추가적인 인프라 필요, 단일 서버에서 필요 없는 네트워크 지연 overhead 발생
  2. DB 락 없이 자바 큐 사용해 배치 처리
    1. 자바 수준에서 제어 가능
    2. 순차적인 메시지 순서를 보장할 경우 추가 로직 필요, 추후 서버 수평 확장시 변경 가능성 높음
  3. MySQL SKIP LOCKED
    1. 데이터베이스 수준에서 제공되는 기능으로 구현이 상대적으로 간단함
    2. 동시성 처리 향상 및 락 대기 시간 감소
    3. MySQL 8.0 이상에서만 동작하는 기능으로 DB에 종속적임

따라서, 추가적인 인프라 도입 없이 서버의 DB 또한 MySQL이였기에 MySQL SKIP LOCKED을 해결 방안으로 채택

📚 Skip Locked 개요

MySQL SKIP LOCKED의 원리

트랜잭션에 의해 행이 잠긴 경우

  1. 일반적인 경우
    1. 잠긴 행을 포함하는 요청 시 트랜잭션은 해당 행 잠금이 해제 될 때까지 기다림
    2. 행 잠김이 해제되면 그때 해당 행을 포함한 결과를 반환
  2. SKIP LOCKED 경우
    1. 잠긴 행을 포함하는 요청 시 트랜잭션은 행 잠금을 해제 할 때까지 기다리지 않고 건너뜀
    2. 잠긴 행을 제외한 결과 값을 반환
    3. 따라서 잠긴 행에 따라 요청 시 일관적이지 않은 결과를 보여줌
    4. 여러 세션이 동일한 대기열과 같은 테이블에 액세스할 때 잠금 경합을 피하기 위해 사용

따라서 아래와 같은 방식으로 동작

SKIP LOCKED Principle

🔧 설계 변경

변경된 아키텍처 개요

Updated ERD

변경된 ERD

  • 하나의 축제(festival)은 여러 개의 티켓(ticket) 종류를 가짐 (OneToMany)
  • 티켓(ticket)은 여러 개의 티켓 재고(ticket_stock)를 가짐 (OneToMany)
    • 티켓 재고만큼 ticket_stock에서 레코드가 생성됨
    • ticket_stock_member_id엔 티켓 재고를 점유한 member_id가 들어감
  • 따라서 아래의 그림과 같이 티켓 재고를 얻는 행위에서 다른 유저가 점유한 레코드의 잠금 해제를 기다리지 않고 잠금이 걸리지 않은 1개의 행을 빠르게 얻어 옴
New Locking Mechanism
  • 결과적으로 잠금에 대한 경합이 일어나지 않기 때문에 쓰레드와 커넥션에 대한 병목이 감소할 것으로 보였음

🚀 성능 테스트

테스트 계획 수립

티켓팅 시나리오

  • 3000, 5000명 기준
  1. 상세 페이지 조회
  2. 티켓 목록 조회
  3. 티켓 결제 가능 여부 조회
  4. 결제 정보 미리보기 페이지 조회
  5. 티켓 결제

결과 분석

3000명 - SKIP LOCKED 적용 전후 비교

3000 Users Comparison

5000명 - SKIP LOCKED 적용 전후 비교

5000 Users Comparison

레퍼런스

https://dev.mysql.com/doc/refman/8.4/en/innodb-locking-reads.html