개요

최근 서비스는 규모가 커짐에 따라서 하나의 서버만 존재하는 모놀리식이 아닌 마이크로서비스를 사용 합니다. 모놀리식 서비스도 단일 프로세스가 아닌 다중 프로세스를 이용하여 동시성 제어가 더욱 중요해졌습니다.

내용

동시성 제어?

다중 사용자 환경을 지원하는 데이터베이스 시스템에서 동시에 실행되는 여러 트랜잭션 간의 간섭으로 문제가 발생하지 않도록 트랜잭션의 실행 순서를 제어하는 기법입니다.

n개의 프로세스가 1개의 데이터베이스에 읽고 쓰기를 하면 개발자가 원하지 않는 방향으로 데이터가 들어가게 됩니다.

예시로 두 명의 사용자가 동시에 갯수가 1개 남은 쿠폰을 발급 받는다면 발급 처리 전에 쿠폰의 갯수가 1개 이상이기 때문에 두 명의 사용자에게 쿠폰이 모두 발급됩니다.

동시성 제어 기법은 크게 2가지로 낙관적 동시성 제어와 비관적 동시성 제어가 있습니다.

낙관적 동시성 제어

같은 데이터가 동시에 수정되지 않는다고 가정합니다. 데이터를 조회하는 시점에 잠금을 걸지 않는 대신 수정 시점에 값이 변경 되었는지 검사합니다.

MVCC가 낙관적 동시 제어로 트랜잭션은 데이터의 특정 시점(snapshot)을 사용하여 작업을 수행합니다. 충돌이 발생하지 않으면 변경 사항을 적용하고 충돌이 발생하면 트랜잭션을 롤백하고 재시도합니다.

비관적 동시성 제어

동시에 같은 사용자들이 접근하여 수정한다고 가정합니다. 데이터를 조회하는 시점에 잠금(locking)을 걸고, 트랜잭션이 종료될 때까지 유지합니다.

잠금 (Locking)이 비관적 동시성 제어의 대표적인 예시로 충돌을 방지하기 위해 데이터에 접근할 때 잠금을 사용합니다. 잠금에는 데이터를 읽기 위한 공유 잠금과 데이터를 읽고 쓰기 위한 배타적 잠금이 있습니다.

큐를 활용하여 동시성 문제를 해결 할 수 있습니다. 비동기적으로 실행되어야 하는 작업을 큐에 추가하면 FIFO방식으로 작업이 처리됩니다.

결론

동시성 제어에 대한 간단한 이론적 지식을 정리해봤습니다. 실무에서는 팀 별, 서비스 별로 다양한 방식으로 동시성 제어를 적용합니다.

단순히 호스트+인스턴스를 통해서 제한을 두는 방법, Redis를 이용하여 spinlock, redlock을 활용하는 방법 등등이 있습니다.

참고