동시성이란 ?
어떤 두 사건이 같은 시간에 일어나는 것을 이르는 말
나의 경우는 여러군데서 동시성 이슈가 발생할 수 있다.
현재까지 구현한 기능에서 보면 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)
'공부' 카테고리의 다른 글
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 |