동시성 문제 - comento-backend-camp/ticket-reservation-server-hyejung GitHub Wiki
동시성 문제
실제 서비스 운영에서는 초당 1개의 서버가 받는 요청은 200tps는 기본, 많으면 1000, 10000 까지도 올라갈 수 있음. (tps : 1초당 처리되는 트랜잭션 타임)
ex. 같은 좌석을 동시에 10000명의 사용자가 동시에 예약 시도를 한다면?
동시성 이슈를 처리하지 않을 경우 10000명 모두 예약에 성공하게 됨.
즉, 동시성 문제를 해결할 수 있어야 함
- RDBMS의 테이블에 동시에 여러 커넥션이 같은 테이블의 row를 수정하면 데이터가 예상과 다르게 변경되는 문제 발생
- 이를 해결하기 위해 RDBMS에서는 Lock을 통해 동시성을 제어하여 ACID를 보장
해결방법
- 분산락을 적용하는 방법
- 최고 수준의 격리 수준(MySQL의 경우,
SERIALIZABLE
)으로 설정- 쿼리별로 lock을 건다.
- 동시에 실행되는 경우 데드락 상태에 빠질 수 있음
- ex. T1과 T2가 좌석의 예약현황을 조회할때 S락을 걸어버리고 T1과 T2가 reservation 테이블에 insert시키고 해당 좌석의 예약상태를 완료로 변경할때 X Lock을 걸려고 시도하는데 T1이 S락으로 해당 row을 점유하고 있고 T2또한 S락으로 해당 row를 점유하고 있기때문에 T1,T2는 서로 S락을 소유하고있지만 X락을 획득하려고 하면서 데드락 상태에 빠지고 timeout으로 두개의 트랜잭션은 모두 실패
- row별로 lock을 건다
SELECT .. FOR UPDATE
문을 이용- FOR UPDATE 구문은 Seriazable레벨에 비해서 데드락은 줄일 수 있음.
- FOR UPDATE문은 타임아웃 구성이 까다롭기 때문에 무한 대기에 빠질수 있음.
- 쿼리별로 lock을 건다.
- 최고 수준의 격리 수준(MySQL의 경우,
- Redis를 이용하는 방법
- 싱글스레드로 이루어져있으므로 들어온 순서로 처리하기에 동시성 문제가 발생되지 않음.