동시성 제어 (낙관적 락, 비관적 락, 분산 락)

2024. 10. 19. 21:13·Spring

낙관적 락(Optimistic Locking)란?

낙관적 락(Optimistic Locking)은 데이터베이스나 멀티스레드 환경에서 여러 사용자가 동일한 데이터를 수정할 때 발생할 수 있는 충돌을 관리하는 방법 중 하나입니다. 낙관적 락은 충돌이 자주 발생하지 않을 것이라고 가정하고, 충돌을 감지하여 처리하는 방식으로 동작합니다. 이 방식은 보통 비전 번호(Versioning)나 타임스템프를 이용해 구현됩니다.

 

낙관적 락 작동 원리

  1. 데이터 조회: 사용자가 데이터를 조회할 때 해당 레코드의 현재 버전 정보를 함께 가져옵니다. 이 버전은 레코드가 수정될 때마다 증가하거나 변경됩니다.
  2. 데이터 수정: 사용자가 데이터를 수정하려고 할 때, 수정하려는 레코드의 현재 버전과 사용자가 처음 조회할 때 가져온 버전 정보를 비교합니다.
  3. 검증: 만약 사용자가 조회한 이후에 다른 사용자가 해당 데이터를 수정해서 버전 정보가 변경되었다면, 충돌이 발생했다고 판단하고 예외를 발생시킵니다. 이때 수정이 실패하고 트랜잭션이 롤백됩니다.
  4. 수정 성공: 만약 버전 정보가 동일하다면, 수정이 성공적으로 이루어지며, 데이터베이스는 해당 레코드의 버전 번호를 증가시킵니다.

낙관적 락 작동 원리

낙관적 락이 사용되는 경우는?

  • 충돌이 적을 것으로 예상되는 상황: 여러 사용자가 동시에 데이터를 수정하는 일이 드물 경우 낙관적 락이 효율적입니다. 충돌이 발생하지 않으면 데이터베이스 락을 잡을 필요 없이 처리할 수 있어 성능이 좋습니다.
  • 버전 관리를 통한 충돌 해결: 예를 들어, User 엔티티에 version 필드가 있다고 가정할 때, 데이터 수정 시 version 값이 변경되었는지 비교하여 충돌을 감지합니다.

비관적 락(Perssimistic Locking)이란?

비관적 락(Pessimistic Locking)은 데이터베이스나 멀티스레드 환경에서 여러 사용자가 동시에 동일한 데이터를 수정할 때 발생할 수 있는 충돌을 예방하기 위해, 미리 락을 걸어 충돌을 방지하는 방법입니다. 비관적 락은 충돌이 자주 발생할 것으로 예상되는 환경에서 사용됩니다.

 

작동 원리

비관적 락은 데이터를 조회하거나 수정할 때 다른 사용자가 해당 데이터에 접근하지 못하도록 락을 설정합니다. 이로 인해 데이터를 수정하는 동안에는 다른 트랜잭션이 그 데이터를 읽거나 수정할 수 없습니다. 주요 흐름은 다음과 같습니다:

 

1. 데이터 조회: 사용자가 데이터를 조회할 때, 데이터를 수정할 의도가 있다면 해당 데이터에 대해 락을 걸고 다른 트랜잭션이 접근하지 못하도록 합니다. 이 락은 주로 쓰기 락(write lock) 또는 독점 락(exclusive lock)이라고 부릅니다.

2. 락 유지: 락이 걸린 동안 다른 트랜잭션은 해당 데이터에 접근할 수 없으며, 락을 획득한 트랜잭션이 완료될 때까지 대기하거나 실패하게 됩니다.

3. 데이터 수정: 락을 획득한 사용자가 데이터를 수정합니다. 이때 수정된 데이터는 다른 트랜잭션이 접근할 수 없으므로 충돌을 방지할 수 있습니다.

4. 락 해제: 트랜잭션이 완료되면 락이 해제되어 다른 트랜잭션이 데이터를 조회하거나 수정할 수 있습니다.

비관적 락의 작동 원리

 

예시로 들자면

비관적 락은 충돌이 빈번하게 발생하는 상황에서 자주 사용됩니다. 예를 들어, 은행의 계좌 잔액을 업데이트하는 트랜잭션에서 두 사용자가 동시에 잔액을 변경하려는 경우, 비관적 락을 통해 한 사용자가 잔액을 수정하는 동안 다른 사용자는 접근할 수 없도록 합니다.

SELECT * FROM account WHERE id = 1 FOR UPDATE;

위 SQL 문은 id가 1인 계좌 데이터를 조회하고 수정할 예정이므로 FOR UPDATE를 통해 해당 계좌에 쓰기 락을 설정합니다. 이 트랜잭션이 완료되기 전까지 다른 사용자는 이 데이터를 수정할 수 없습니다.

 

비관적 락의 종류

  • 읽기 락(Shared Lock, S-lock): 여러 트랜잭션이 데이터를 읽을 수 있지만, 데이터를 수정하려는 트랜잭션은 락이 걸릴 수 없습니다. 즉, 여러 사용자가 동시에 데이터를 읽을 수는 있지만, 수정하려는 사용자는 대기해야 합니다.
  • 쓰기 락(Exclusive Lock, X-lock): 데이터를 읽거나 수정하려는 트랜잭션이 락을 설정하여 다른 트랜잭션이 해당 데이터를 읽거나 수정하지 못하게 합니다.

비관적 락의 장단점

장점

  • 충돌 예방: 미리 락을 걸기 때문에 동시에 데이터를 수정하는 과정에서 발생할 수 있는 충돌을 방지할 수 있습니다.
  • 데이터 무결성 보장: 동시 접근으로 인해 발생할 수 있는 데이터 일관성 문제를 미리 차단합니다.

단점

  • 성능 저하: 락을 걸면 다른 트랜잭션들이 해당 데이터에 접근하지 못하고 대기해야 하기 때문에 시스템의 성능이 저하될 수 있습니다. 특히, 트랜잭션이 오래 지속되거나, 락이 걸린 상태에서 대기 시간이 길어지면 병목 현상이 발생할 수 있습니다.
  • 교착 상태(Deadlock) 발생 가능성: 두 트랜잭션이 서로 다른 리소스를 락을 걸고 상호 대기하는 상태가 되면, 교착 상태가 발생할 수 있습니다.

분산 락(Distributed Lock)이란?

분산 락(Distributed Lock)은 분산 시스템 환경에서 여러 노드(서버)가 동일한 자원에 접근하여 데이터를 수정하거나 읽을 때, 데이터의 일관성과 무결성을 보장하기 위해 사용하는 락 메커니즘입니다. 일반적인 락이 단일 시스템 내에서만 동작하는 것과 달리, 분산 락은 여러 서버나 프로세스가 서로 다른 물리적 위치에 있는 상황에서도 자원의 동시성을 제어할 수 있도록 설계됩니다.

 

분산 시스템에서는 여러 서버가 병렬로 처리 작업을 수행하는데, 동일한 자원을 여러 서버가 동시에 접근할 경우 데이터 충돌이나 일관성 문제가 발생할 수 있습니다. 분산 락은 이러한 문제를 방지하기 위해 특정 자원에 대해 서로 다른 노드들이 동시에 접근하지 못하도록 제한하는 역할을 합니다.

 

분산 락의 필요성

 

분산 시스템에서 각 서버는 독립적으로 실행되며 네트워크를 통해 자원에 접근합니다. 이 과정에서 발생할 수 있는 문제는 다음과 같습니다:

  • 데이터 일관성 문제: 여러 서버가 동일한 자원을 동시에 업데이트하면 데이터가 꼬일 수 있습니다.
  • 동시성 제어: 한 서버가 자원을 업데이트하는 동안 다른 서버는 해당 자원에 접근해서는 안 됩니다.
  • 멀티노드 환경: 여러 노드에서 동일한 자원에 접근할 때, 단일 서버에서 락을 거는 방식으로는 관리할 수 없습니다.

분산 락의 주요 구현 방법

 

분산 락을 구현하는 방법은 여러 가지가 있습니다. 대표적으로 Redis, Zookeeper, Consul 등과 같은 도구를 사용하여 분산 락을 관리할 수 있습니다.

 

1. Redis 기반 분산 락 (Redlock 알고리즘)

 

Redis는 인메모리 데이터 저장소로 주로 캐시로 사용되지만, Redlock 알고리즘을 통해 분산 락을 구현할 수 있습니다. 이 방식은 다중 Redis 인스턴스를 이용해 분산 환경에서 락을 관리합니다.

  • 락 획득: 노드는 여러 Redis 인스턴스에 동일한 키로 락을 설정하려 시도합니다. 이를 성공적으로 설정하면 해당 자원에 대한 락을 획득하게 됩니다.
  • TTL(Time To Live): Redis에 설정된 락은 유효 시간(TTL)을 가지며, 이 시간이 지나면 자동으로 해제됩니다. 이는 서버가 갑작스럽게 다운되거나 네트워크 문제로 락을 해제하지 못하는 상황을 방지합니다.
  • 락 해제: 작업이 완료되면 노드는 Redis에 락 해제 명령을 보내 락을 해제합니다.

 

2. Zookeeper 기반 분산 락

 

Zookeeper는 분산 시스템의 자원 관리 및 동기화를 위한 서비스입니다. Zookeeper는 ZNode라는 특수한 노드를 이용해 락을 관리합니다.

  • Ephemeral ZNode: Zookeeper에서는 일시적인 노드(Ephemeral ZNode)를 생성하여 락을 구현합니다. 노드는 락을 얻기 위해 Zookeeper에 ZNode를 생성하며, 락이 해제되면 해당 ZNode가 삭제됩니다.
  • 락 획득: 하나의 노드만 ZNode를 생성할 수 있으며, 나머지 노드는 대기 상태로 전환됩니다. 락을 가진 노드가 작업을 마치면 ZNode를 삭제하고, 다음 노드가 락을 획득합니다.
  • 자동 해제: 락을 가진 노드가 죽거나 네트워크가 끊기면 Ephemeral ZNode가 자동으로 삭제되어 다른 노드가 락을 획득할 수 있게 됩니다.

 

3. Consul 기반 분산 락

 

Consul은 서비스 디스커버리와 설정 관리를 제공하는 분산 시스템 툴입니다. Consul은 **세션(session)**을 사용하여 분산 락을 구현합니다.

  • 세션 생성: 노드는 특정 키에 대해 세션을 생성하고 락을 시도합니다.
  • 락 획득: 세션이 성공적으로 생성되면 해당 노드는 자원에 대한 락을 얻습니다.
  • 세션 유지: 락을 유지하기 위해 세션은 Consul 서버와 주기적으로 heartbeat를 주고받습니다.
  • 세션 만료: 노드가 다운되거나 heartbeat를 놓치면 세션이 만료되고 락이 해제됩니다.

분산 락의 특징

 

  • TTL 설정: 분산 락을 사용할 때는 보통 TTL(Time To Live)을 설정해 락이 일정 시간이 지나면 자동으로 해제되도록 합니다. 이는 서버가 갑작스레 다운되었을 때 락이 영구적으로 걸려 자원을 사용할 수 없게 되는 문제를 방지합니다.
  • 락 해제: 락을 획득한 노드는 작업이 끝난 후 명시적으로 락을 해제해야 합니다. 만약 노드가 죽거나 네트워크 오류가 발생하면 TTL을 통해 자동 해제가 이루어집니다.
  • 정확한 시간 동기화: 분산 시스템에서 락을 다룰 때 각 서버 간의 시간 차이가 문제가 될 수 있습니다. 이 때문에 Redlock과 같은 알고리즘은 서버 간 시간을 최대한 동기화하고 일관되게 유지하는 것을 중요하게 생각합니다.

분산 락의 장점

  • 데이터 일관성 보장: 여러 서버가 동일한 자원에 동시에 접근하는 것을 방지하여 데이터 일관성과 무결성을 보장합니다.
  • 다중 노드 간 동시성 제어: 여러 노드에서 자원을 동시에 사용할 때 동시성 문제를 해결할 수 있습니다.

분산 락의 단점

  • 복잡성 증가: 단일 시스템에서의 락보다 구현이 복잡하며, 네트워크 장애나 노드 간 통신 실패 등으로 인해 예상치 못한 문제가 발생할 수 있습니다.
  • 성능 저하: 락을 걸고 해제하는 과정에서 네트워크 지연이 발생할 수 있어 시스템 성능에 영향을 미칠 수 있습니다.
반응형

'Spring' 카테고리의 다른 글

Dispatchservlet이 Spring boot에서 controller로 이동하는 과정  (0) 2025.02.25
Spring boot 버전 정리  (2) 2024.12.02
Transactional 관심사의 분리를 통해 로그 기록 남기기  (0) 2024.10.08
단위테스트, 통합테스트  (1) 2024.10.01
Fetch Type:LazyLoading vs EagerLoading  (0) 2024.09.30
'Spring' 카테고리의 다른 글
  • Dispatchservlet이 Spring boot에서 controller로 이동하는 과정
  • Spring boot 버전 정리
  • Transactional 관심사의 분리를 통해 로그 기록 남기기
  • 단위테스트, 통합테스트
wanduek
wanduek
차근차근 쌓아가는 지식
  • wanduek
    완득님의 블로그
    wanduek
  • 전체
    오늘
    어제
    • 분류 전체보기 (194)
      • Onboarding (0)
      • 아티클 (0)
      • SQL 정리 (20)
      • 웹개발 기초정리(프엔) (9)
      • (Java)코테연습 (27)
      • 미니 프로젝트 (9)
        • 자기소개 웹페이지 (5)
        • 수강생 관리 프로그램(Java) (4)
      • GitHub 오류 및 명령어 정리 (7)
      • Java 문법정리 (Array부터) (17)
      • Java로 이용한 기능 (2)
      • Web지식 (12)
        • web3 (6)
        • 네트워크 (6)
      • 인텔리제이 오류 대처 방법 (1)
      • Computer Science (7)
      • Spring (38)
        • 미니 프로젝트(배달) (2)
        • Spring 트러블 슈팅 (3)
        • QueryDSL, JPQL (3)
        • 미니 프로젝트(뉴스피드) (5)
        • 미니 프로젝트(Trello) (2)
      • 개발자 밋업 (1)
      • Docker (2)
      • Redis (1)
      • AWS (6)
        • AWS 트러블 슈팅 (2)
      • Jmeter (2)
      • 우리 지금 만나 (12)
      • Kafka (1)
      • RabbitMQ (2)
        • 트러블 슈팅 (1)
      • STOMP (2)
      • WebSocket (3)
        • 트러블 슈팅 (2)
      • Node.js (2)
      • Elastic Search (2)
      • Nginx (1)
      • 퍼블엘 (2)
      • openresty (3)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    jquery
    json
    백앤드개발자 #초심자
    groupby
    git
    where
    fetch
    SQL
    ㅏㄷ
    github
  • 최근 댓글

  • 최근 글

  • 반응형
  • hELLO· Designed By정상우.v4.10.0
wanduek
동시성 제어 (낙관적 락, 비관적 락, 분산 락)
상단으로

티스토리툴바