본문 바로가기
공부

동시성(Concurrency) 이슈

by son_i 2023. 12. 13.
728x90

동시성이란 ?

어떤 두 사건이 같은 시간에 일어나는 것을 이르는 말

 

나의 경우는 여러군데서 동시성 이슈가 발생할 수 있다.

현재까지 구현한 기능에서 보면 A->B에게 , B->A에게 동시에 친구요청을 거는 일이 발생한다면 동시성 이슈가 발생하게 된다.

 

Y ?)

- A가 B에게 친구요청을 걸었을 때 WAIT 상태의 Friend 컬럼 생성.

- A->B 요청이 처리되기 전의 상태로 B가 A에게 친구요청을 걸었을 때 똑같이 WAIT상태의 컬럼 생성.

 

정상적으로 A->B, B->A 요청이 순차적으로 들어왔다면 B가 A에게 친구요청을 걸수 없다. (이미 상대에게 요청이 들어온 건에 대해서 자신이 또 상대에게 요청을 걸 수 없게 해놨으므로)

 

위와 같은 상황을 경쟁 상태라고 한다.

경쟁상태(race condition)

둘 이상의 입력 또는 조작의 타이밍이나 순서 등이 결과 값에 영향을 줄 수 있는 상태

 

친구요청을 거는 과정에서 발신자, 수신자를 DB에서 조회해 Entity를 받아오게 되고

validateRequest에서 유효성을 검증한다.

 

유효성에서 이상이 없다면 요청 정보를 저장(Write)하게 된다.

 

동시성 문제 해결 방법

동시에 일어났을 때 어떤 작업을 먼저 순차적으로 작동하게 할지를 정해주면 된다고 생각했다.

 

예전에 cs를 배울 때 synchronized로 data의 thread-safe를 보장해줄 수 있는게 생각났다.

 

1. Synchronized

  • 메소드에 명시해주면 하나의 스레드만 접근이 가능.
  • 멀티 스레드 환경에서 스레드간 데이터 동기화를 시켜주기 위해서 자바에서 제공하는 키워드
  • 공유되는 데이터의 Thread-safe유지를 위해 사용하고 스레드간 동기화를 시켜서 thread-safe하게 만듦.
  • 자바지원 synchroized은 현재 데이터를 사용하고 있는 해당 스레드를 제외하고 나머지 스레드들의 접근을 막아 순차적으로 데이터에 접근할 수 있도록 해줌.

* 트랜잭션과 동기화는 다른 개념이다.

  - 트랜잭션은 begin - 로직 실행 - commit의 순서로 진행되는데, 하나의 트랜잭션이 커밋되기 전에 다른 트랜잭션이 실행될 수 있고, 이로 인해 동시성 이슈가 발생한다.

  - synchronized 키워드는 메소드가 한 번에 하나의 스레드에서만 실행할 수 있도록 Locking 하는 것. 

 

따라서 thread A의 트랜잭션에서 request() 메소드가 수행되고 커밋되기 전에 thread B의 request() 메소드가 시작되기 때문에 synchronized 키워드를 통해 동시성 문제를 해결할 수 없다. 

 

트랜잭션이 적용되기 전단계에서 synchronized 키워드를 적용하거나, @Transactional 어노테이션을 제거해서 동시성 이슈를 해결할 수 있다.

 

문제점

그런데 synchronized로 메소드의 모든 동작에 lock을 걸면 하나의 스레드만 접근이 가능하기 때문에 많은 오버헤드가 발생한다.

또한 synchronized는 동일한 프로세스 내의 스레드 단위에서만 동시성을 보장한다.

즉 단일 서버라면 동시성 이슈가 발생하지 않지만 웹과 같이 여러 대의 서버를 활용하면 동시성을 보장할 수 없다. 

 

 

-> 트랜잭션 격리 수준을 SERIALIZALE로 변경하면 성능이 매우 떨어지고 Deadlock 이 발생한다.

SERIALIZALE 특징을 보면 이해할 수 있는데 

SERIALIZALE은 읽기 작업도 공유잠금(읽기 잠금)을 획득해야하며 동시에 다른 트랜잭션은 이 레코드를 변경할 수 없다. 

  -->즉, 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없다.

 

읽기 락은 Lcok을 얻은 세션에서 읽기만 간으하며 쓰기(insertm, update, delete)등의 작업을 수행할 수 없다.

 

두 트랜잭션이 동시에 실행될 경우 읽기락을 걸고 쓰기락을 걸기 때문에  Deadlock이 발생한다. 

 

트랜잭션 격리 수준 관련 참고 블로그

https://zzang9ha.tistory.com/381

 

참고

https://zzang9ha.tistory.com/443



나는 그래서  Redis를 활용해 동시성이슈를 해결해보려고 한다.

GiftFunding) Redis를 이용한 동시성 이슈 해결 (tistory.com)

 

GiftFunding) Redis를 이용한 동시성 이슈 해결

 

soni-developer.tistory.com

 

'공부' 카테고리의 다른 글

Websocket 프로토콜  (1) 2024.01.01
data.sql 실행 안 될 때  (0) 2023.12.15
트랜잭션  (0) 2023.12.13
Page로 페이지 처리하기  (0) 2023.12.10
Elasticsearch) Mapping  (1) 2023.12.08