[데이터베이스] 분산 락
분산 락
하나의 서버 클라이언트(이하 클라이언트)이 하나의 데이터베이스에 접근하는 경우 프로세스 내 멀티 스레드 환경에서 스레드 간 데이터 경합을 방지하기 위해 동시 실행 제어(concurreny control)가 필요하다. 락(lock)이란 데이터베이스의 공유 리소스(예: 테이블, 로우 등)를 대상으로 수행하는 트랜잭션 동시 실행 제어 기법 중 하나이다. 하나 이상의 클라이언트가 하나의 데이터베이스에 접근하는 경우에는 스레드 뿐만 아니라 프로세스 간 데이터 경합을 방지하기 위한 데이터 락이 필요하다. 두 경우 모두 데이터베이스에서 제공하는 락 메커니즘을 사용하여 데이터의 일관성을 유지할 수 있다.
분산 시스템(distributed system)이란 데이터베이스에 접근하는 클라이언트 또는 데이터베이스가 여러 개로 구성되는 시스템을 말한다. 여러 클라이언트가 동일한 데이터베이스에 동시적으로 접근하는 경우 멀티 스레드 간 데이터 경합 뿐만 아니라 프로세스 간 데이터 경합을 방지하기 위한 데이터 락이 필요하다.
단일 클라이언트로 구성된 시스템과 여러 클라이언트로 구성된 분산 시스템 모두 공유 리소스에 대한 트랜잭션의 동시적인 접근 상황은 동일하게 발생하므로 락을 통한 동시 실행 제어가 필요하다. 이때 락을 관리하는 역할을 수행하는 소프트웨어 컴포넌트를 락 관리자(lock manager)라고 한다. 락 관리자는 하나의 트랜잭션이 공유 리소스에 대한 락을 획득하고 독점적으로(exclusive) 점유하여 사용하는 동안 다른 트랜잭션이 해당 데이터에 접근할 수 없도록 한다.
하나의 락 관리자가 락을 관리하는 경우 해당 락을 중앙 집중식 락(centralized lock) 또는 데이터베이스 락(database lock)이라고 한다. 일반적으로 중앙 집중식 락의 관리 주체는 단일 데이터베이스이다. 트랜잭션을 지원하는 대부분의 관계형 데이터베이스는 중앙 집중식 락을 제공한다. 이 경우 데이터베이스가 직접 락을 관리하여 트랜잭션의 동시 실행을 제어한다.
중앙 집중식 락의 대표적인 예는 데이터베이스가 자체적으로 제공하는 테이블의 로우 락(row lock)이다. 테이블의 한 로우에 동시적으로 접근하는 경우 해당 로우에 대한 락을 통해 동시 접근을 제어한다.
중앙 집중식 락은 주로 단일 데이터베이스에 대해 수행되는 트랜잭션의 동시 실행 제어를 처리하는데 사용된다. 클라이언트가 여러 개인지 여부에 관계 없이 중앙 집중 락은 동시 실행 제어를 처리한다. 즉, 다중 클라이언트 및 단일 데이터베이스로 구성된 분산 시스템 환경에서도 동시 실행 제어 처리에 사용된다는 의미이다. 단, 다중 데이터베이스 구성 환경에서는 동시 실행 제어를 처리하기 어려우며 분산 락과 같은 별도의 락 메커니즘이 필요하다.
분산 락(distributed lock)이란 분산 시스템에서 여러 클라이언트가 동시에 공유 리소스에 접근하는 것을 제어하기 위한 락 메커니즘이다. 클라이언트 또는 데이터베이스가 여러 개로 구성되는 분산 시스템 환경에서 락 관리는 단일 환경 보다 매우 복잡한데, 그 이유는 다음과 같다.
- 분산 시스템에서는 여러 서비스들이 네트워크 상에서 분리되어 존재하므로 다양한 네트워크 분할(network partition) 상황이 발생할 수 있다. 서비스들 중 일부 서비스 간 통신이 불가능해지면 락의 획득과 해제 과정이 정상적으로 수행되지 않으며 이는 데이터 비일관성 문제를 일으킨다.
- 분산 시스템에서는 여러 서비스들이 자체적인 시계(clock)를 가지고 있으며, 이 시계들은 서로 완벽하게 동기화되지 않는다. 특정 시간을 기준으로 공유 리소스의 락을 설정하는 알고리즘에서 시간 오차는 락의 정확성을 떨어뜨릴 수 있다.
- 서비스들 중 일부 서비스에 장애가 발생하였을 때 나머지 서비스들을 대상으로 락 관리를 어떻게 안전하게 수행할지 고려해야 한다. 예를 들어 특정 클라이언트가 락을 획득을 하고 있던 도중 장애가 발생하여 트랜잭션을 완료할 수 없어 락을 해제할 수 없는 경우 다른 클라이언트가 락을 획득할 수 있도록 락을 관리해야 한다. 이 경우 클라이언트의 장애에 대한 처리를 수행해야 한다.
이러한 이유로 인해 분산 시스템에서의 락 관리는 보다 복잡한 알고리즘을 필요로 한다.
데이터베이스에 접근하는 클라이언트의 다중 구성 여부, 데이터베이스의 다중 구성 여부에 따라 필요한 락이 달라지게 된다.
- 단일 클라이언트 (멀티 스레드 구현) + 단일 데이터베이스 구성: 낙관적 락(클라이언트의 애플리케이션 수준의 동기화를 통한 트랜잭션의 동시 실행 제어), 비관적 락, 분산 락 중 하나를 사용하여 트랜잭션의 동시 실행을 제어할 수 있다.
- 다중 클라이언트 + 단일 데이터베이스 구성: 낙관적 락 또는 비관적 락만으로 트랜잭션의 동시 실행 제어를 할 수 있다. 하지만 특정 상황에서는 분산 락이 필요하다.
- 다중 클라이언트 + 다중 데이터베이스 구성: 낙관적 락 또는 비관적 락만으로 트랜잭션의 동시 실행 제어를 하기 어렵다. 분산 락이 필요하다.
분산 락을 통한 비즈니스 로직 동시 실행 제어
공유 리소스가 데이터베이스에 저장된 데이터이고, 공유 리소스에 대한 접근이 데이터베이스 트랜잭션 경계 내에서 이루어진다면 트랜잭션 동시 실행 제어를 위한 데이터베이스가 제공하는 중앙 집중식 락 만으로도 충분하다. 예를 들어, 하나의 트랜잭션 내에서 데이터베이스에 대한 접근만 수행한다면 중앙 집중식 락을 통해 서로 다른 스레드 간, 또는 서로 다른 프로세스 간 트랜잭션 동시 실행 제어를 통해 데이터의 일관성을 유지할 수 있다.
그러나 공유 리소스가 데이터베이스에 저장된 데이터가 아니고, 공유 리소스에 대한 접근이 데이터베이스 트랜잭션의 경계를 넘어서는 경우 데이터베이스 수준의 동시 실행 제어는 공유 리소스에 대한 동시 접근을 제어할 수 없다. 예를 들어, 트랜잭션 내에 데이터베이스의 데이터 대한 접근과 API 호출이 함께 존재하는 경우 중앙 집중식 락은 데이터베이스의 데이터에 대한 동시 접근만 제어하며 API 호출의 동시 실행을 제어하지는 않는다. 이 경우 단일 클라이언트의 경우 애플리케이션 수준의 스레드 동시 실행 제어를 위한 동기화(synchronzation), 다중 클라이언트의 경우 프로세스 동시 실행 제어를 위한 분산 락이 필요하다.
- 단일 클라이언트 (멀티 스레드 구현): 단일 프로세스 내부에서 스레드 간 동시 실행 제어를 위해 애플리케이션이 제공하는 동기화 기법을 사용한다.
- 다중 클라이언트: 다중 프로세스 간 동시 실행 제어를 위해 분산 락을 사용한다.
CAP 정리
컴퓨터 과학에서 CAP 정리란, 일관성(consistency), 가용성(availability), 분할 허용성(partition tolerance) 세 가지 특성 모두를 동시에 지원하는 분산 시스템은 없다는 것을 말한다. CAP 정리는 데이터베이스에 관련된 이론이며, 여기서 의미하는 분산 시스템이란 데이터를 여러 데이터베이스 노드에 분할 또는 복제하여 저장하는 분산 데이터 저장소를 말한다. CAP 정리에 따르면 분산 시스템은 특정 시간에 다음 세 가지 특성 중 최대 두 가지 특성을 제공하는 것이 보장된다. CAP 정리는 분산 시스템에 대한 것이므로 네트워크 분할(network partition)이라는 개념을 포함한다.
CAP 정리는 다중 데이터베이스로 구성된 시스템에 대한 것이므로 분산 락과도 연관이 있다. 분산 락은 여러 클라이언트가 데이터베이스에 접근하는 경우 데이터의 일관성을 보장하기 위해 사용된다. 즉, 분산 락은 네트워크 분할 상황에서 일관성을 유지한다. 클라이언트가 락을 획득한 상황에서 네트워크 분할이 발생했을 때 클라이언트와 데이터베이스의 통신이 불가능해지면 분산 락 관리자는 다른 클라이언트는 락을 획득할 수 없게 만들어 작업을 수행하지 못하게 한다.
분산 락 구현 방법
주키퍼
헤이즐캐스트 락 API
레드락 알고리즘
레디스 데이터베이스를 사용하여 분산 락 관리를 수행할 수 있다. 레디스는 분산 락의 표준 알고리즘을 제공하는데 이를 레드락(Redlock) 알고리즘이라고 한다.
참고
- https://martin.kleppmann.com/2016/02/08/how-to-do-distributed-locking.html
- https://redis.io/docs/latest/develop/use/patterns/distributed-locks/
- https://redisson.org/docs/data-and-services/locks-and-synchronizers/
- https://docs.hazelcast.com/imdg/4.2/data-structures/fencedlock
- https://docs.hazelcast.com/imdg/4.2/cp-subsystem/fencedlock
- https://redisson.org/glossary/java-fencedlock.html
Comments