동시성 문제 해결 방법

청포도봉봉이·2023년 6월 30일
0

메모오

목록 보기
10/11

동시에 같은 DB Table row 를 업데이트 하는 상황을 방어하기 위해 어떻게 개발하실 건지 그에 관한 해결 방법이 뭔지 찾고 정리해보았다.

동시성 문제

동시성 문제: 동일한 하나의 데이터에 2개 이상의 스레드 혹은 세션에서 가변 데이터를 동시에 제어할 때 나타는 문제로 하나의 세션이 데이터를 수정 중일때
다른 세션에서 수정 전의 데이터를 조회해 로직을 처리함으로써 데이터의 정합성이 깨지는 문제이다.


해결 방법

DataBase에서 트랜잭션의 격리수준(Transaction Isolation Level)을 설정


비관적 Locking

  • READ UNCOMMITTED
    • 실행되고 있는 다른 트랜잭션이 리소스를 변경시키고 커밋하기 이전이라도 값을 읽어갈 수 있다
    • Resource에 대해 shared lock이 발생하지 않아서, Rollback 될 데이터도 읽어 올 수 있으므로 데이터의 일관성이 어긋날 수 있다
    • 어떠한 lock도 걸지 않는다.
  • READ COMMITTED
    • 이때까지 커밋된 데이터만을 읽는 방식이다.
    • 동일 트랜잭션 내에서 일관성을 보장하지 않는다. 한 트랜잭션에 두번의 읽기를 할 경우 값이 다르게 나올 수 있다
    • 트랜잭션동안 접근하는 행에 대해 shared lock이 걸린다.
  • REPEATABLE READ
    • 동일 트랜잭션 내에서 일관성을 보장한다.
    • 트랜잭션 동안 다른 트랜잭션은 해당 행에 대해 UPDATE가 불가능하다.
    • 읽기 시 snapshot을 만들어 놓고 한 트랜잭션 내에서는 커밋하기전까지 그 snapshot 만을 읽는다.
    • 트랜잭션 동안 접근하는 행에 대해 shared lock 이 발생한다.
  • SERIALIZABLE
    • 트랜잭션 동안 다른 트랜잭션은 해당 테이블에 INSERT or UPDATE 가 불가능하다.
    • 리소스가 속한 테이블 전체에 shared lock을 건다.

낙관적 Locking

  • SELECT FOR UPDATE 를 통해 명시적인 exclusive

Message Queue를 사용한다.

  • Queue의 특성상 하나씩 선입선출을 보장하기 때문에 한개의 메시지 큐를 두면 동시에 들어오는 많은 요청을 순서를 보장하며 처리할 수 있다.

Redis를 활용한다

  • Redis란 key-value 구조의 비정형 데이터를 저장하고 관리하기 위한 오픈 소스 기반의 비 관계형 인메모리 DBMS이다.
  • Redis의 다양한 특징 중에서도 Single Threaded 한 특징 즉, 한 번에 하나의 명령만 처리할 수 있는 특징 때문에 동시성 문제를 해결하는데 많이 사용된다.

Java를 사용한다면

Synchronized 키워드를 활용한 동기화 로직

  • synchronized를 이용하면 현재 접근하고 있는 메서드에 하나의 스레드만 접근할 수 있도록 작동한다.
  • 자바에서 지원하는 synchronized는 현재 데이터를 사용하고 있는 해당 스레드를 제외하고 나머지 스레드들은 데이터 접근을 막아 순차적으로 데이터에 접근할 수 있도록 해준다.

volatile 키워드를 이용하면서 현재 스레드에 저장된 값과 메인 메모리에 저장된 값을 비교

  • volatile 키워드를 사용하면 CPU 메모리 영역에 캐싱 된 값이 아니라 항상 최신의 값을 가지도록 메인 메모리 영역에서 값을 참조하도록 할 수 있다. -> 즉, 동일 시점에 모든 스레드가 동일한 값을 가지도록 동기화한다.
  • 일치하는 경우 새로운 값으로 교체(thread-safe 한 상태이므로 로직 수행)
  • 일치하지 않는 경우 실패 후 재시도(thread-safe 하지 않은 상태였으므로 재시도)
profile
자존감 낮아질 시간에 열심히 학습하고 커밋하자

0개의 댓글