세션 및 분산 잠금 개요

세션 및 분산 잠금 개요 (Sessions and distributed locks overview)

이 문서는 Consul의 세션(Session) 메커니즘과 이를 활용한 분산 잠금(distributed lock) 구축에 대해 설명해 드릴게요. 세션이 어떻게 노드·헬스 체크·키/값 데이터를 묶어주고, 잠금을 관리하는지 핵심 동작을 이해할 수 있어요.

출처: 문서

본문

Consul은 분산 잠금을 구축하는 데 사용할 수 있는 세션 메커니즘을 제공합니다. 세션은 노드, 헬스 체크, 키/값 데이터 사이의 바인딩 레이어 역할을 합니다. 이들은 세밀한 잠금(granular locking)을 제공하도록 설계되었으며, The Chubby Lock Service for Loosely-Coupled Distributed Systems [https://research.google/pubs/the-chubby-lock-service-for-loosely-coupled-distributed-systems/]에서 많은 영감을 받았습니다.

세션 설계 (Session Design)

Consul의 세션은 매우 구체적인 의미(semantics)를 가진 계약(contract)을 나타냅니다. 세션이 구성될 때 노드 이름, 헬스 체크 목록, 동작(behavior), TTL, lock-delay가 제공될 수 있습니다. 새로 구성된 세션에는 이를 식별하는 데 사용할 수 있는 명명된 ID가 제공됩니다. 이 ID는 KV 저장소와 함께 잠금(상호 배제를 위한 조언적 메커니즘)을 획득하는 데 사용할 수 있습니다.

아래는 이러한 구성 요소 간의 관계를 보여주는 다이어그램입니다.

Consul이 제공하는 계약은 다음 상황 중 하나라도 발생하면 세션이 무효화된다는 것입니다:

  • 노드가 등록 해제됨
  • 헬스 체크 중 하나가 등록 해제됨
  • 헬스 체크 중 하나가 critical 상태가 됨
  • 세션이 명시적으로 파괴됨
  • 해당되는 경우 TTL이 만료됨

세션이 무효화되면 파괴되어 더 이상 사용할 수 없습니다. 연결된 잠금에 일어나는 일은 생성 시점에 지정된 동작(behavior)에 따라 다릅니다. Consul은 release와 delete 동작을 지원합니다. 아무것도 지정하지 않으면 release 동작이 기본값입니다.

release 동작이 사용되는 경우 세션과 연결되어 보유된 모든 잠금이 해제되고 키의 ModifyIndex가 증가합니다. 반대로 delete 동작이 사용되면 보유된 잠금에 해당하는 키가 단순히 삭제됩니다. 이를 사용하여 Consul이 자동으로 삭제하는 임시(ephemeral) 항목을 만들 수 있습니다.

이것은 단순한 설계이지만 다양한 사용 패턴을 가능하게 합니다. 기본적으로 가십 기반 실패 감지기(failure detector) [/consul/docs/concept/gossip]가 연결된 헬스 체크로 사용됩니다. 이 실패 감지기는 Consul이 잠금을 보유한 노드가 실패했을 때 이를 감지하고 잠금을 자동으로 해제할 수 있게 해줍니다. 이 능력은 Consul 잠금에 라이브니스(liveness)를 제공합니다. 즉, 실패 상황에서도 시스템이 계속 진행할 수 있습니다. 그러나 완벽한 실패 감지기는 없기 때문에, 잠금 소유자가 여전히 살아 있는데도 잠금이 해제되는 오탐(false positive)이 발생할 수 있습니다. 이는 일부 안전성(safety)을 희생한다는 뜻입니다.

반대로 연결된 헬스 체크가 없는 세션을 만들 수도 있습니다. 이렇게 하면 오탐 가능성이 제거되고 라이브니스를 안전성과 맞바꿉니다. 기존 소유자가 실패했더라도 Consul이 잠금을 절대 해제하지 않을 것이라고 확신할 수 있습니다. Consul API는 세션을 강제로 파괴할 수 있기 때문에, 분할 뇌(split-brain) 가능성을 배제하면서 실패 시 운영자가 개입해야 하는 시스템을 구축할 수 있습니다.

세 번째 헬스 체크 메커니즘은 세션 TTL입니다. 세션을 만들 때 TTL을 지정할 수 있습니다. TTL 간격이 갱신되지 않고 만료되면 세션이 만료되고 무효화가 트리거됩니다. 이러한 유형의 실패 감지기는 하트비트 실패 감지기(heartbeat failure detector)라고도 알려져 있습니다. 이는 서버에 더 큰 부담을 주므로 가십 기반 실패 감지기보다 확장성이 떨어지지만, 일부 경우에는 적합할 수 있습니다. TTL의 계약은 무효화의 하한을 나타낸다는 것입니다. 즉, Consul은 TTL에 도달하기 전에는 세션을 만료시키지 않지만 TTL 이후로 만료를 지연시킬 수 있습니다. TTL은 세션 생성 시, 세션 갱신 시, 리더 장애 조치(failover) 시 갱신됩니다. TTL을 사용할 때 클라이언트는 시계 스큐(clock skew) 문제를 인지해야 합니다. 즉, 클라이언트와 Consul 서버에서 시간이 같은 속도로 진행되지 않을 수 있습니다. 보수적인 TTL 값을 설정하고 네트워크 지연과 시간 스큐를 고려하여 TTL보다 미리 갱신하는 것이 좋습니다.

마지막 미묘한 점은 세션이 lock-delay를 제공할 수 있다는 것입니다. 이는 0에서 60초 사이의 시간 지속 시간입니다. 세션 무효화가 발생하면 Consul은 lock-delay 간격 동안 이전에 보유한 잠금이 다시 획득되지 않도록 방지합니다. 이는 Google의 Chubby에서 영감을 받은 안전 장치입니다. 이 지연의 목적은 잠재적으로 여전히 살아 있는 리더가 무효화를 감지하고 일관되지 않은 상태로 이어질 수 있는 요청 처리를 중지할 시간을 주는 것입니다. 완벽한 방법은 아니지만 애플리케이션 로직에 sleep 상태를 도입할 필요를 없애고 많은 문제를 완화하는 데 도움이 됩니다. 기본값은 15초 지연이지만, 클라이언트는 0 지연 값을 제공하여 이 메커니즘을 비활성화할 수 있습니다.

K/V 통합 (K/V Integration)

KV 저장소와 세션 간의 통합은 세션이 사용되는 주요 장소입니다. 세션은 사용 전에 먼저 생성되어야 하며, 그 후 ID로 참조됩니다.

KV API는 acquire 및 release 작업을 지원하도록 확장되었습니다. acquire 작업은 Check-And-Set 작업처럼 작동하지만, 기존 잠금 보유자가 없는 경우에만 성공할 수 있습니다(현재 잠금 보유자는 다시 acquire할 수 있음, 아래 참조). 성공하면 일반 키 업데이트가 발생하지만 LockIndex도 증가하고 Session 값은 잠금을 보유한 세션을 반영하도록 업데이트됩니다.

acquire 동안 잠금이 이미 해당 세션에 의해 보유된 경우 LockIndex는 증가하지 않지만 키 내용은 업데이트됩니다. 이를 통해 현재 잠금 보유자는 잠금을 포기하고 다시 획득하지 않고도 키 내용을 업데이트할 수 있습니다.

일단 보유되면 동일한 세션을 제공하는 해당 release 작업을 사용하여 잠금을 해제할 수 있습니다. 이 역시 잘못된 세션이 주어지면 요청이 실패하므로 Check-And-Set 작업처럼 작동합니다. 중요한 점은 잠금이 세션의 생성자가 아니어도 해제될 수 있다는 것입니다. 이는 설계상 의도된 것으로, 운영자가 필요할 때 개입하여 세션을 강제 종료할 수 있게 해줍니다. 앞서 언급했듯이 세션 무효화는 보유된 모든 잠금의 해제 또는 삭제를 유발합니다. 잠금이 해제될 때 LockIndex는 변경되지 않지만 Session은 지워지고 ModifyIndex는 증가합니다.

이러한 의미(Chubby에서 크게 차용함)는 (Key, LockIndex, Session) 튜플이 고유한 "시퀀서(sequencer)" 역할을 하도록 합니다. 이 sequencer는 전달되어 요청이 현재 잠금 보유자에게 속하는지 확인하는 데 사용할 수 있습니다. acquire할 때마다 LockIndex가 증가하므로, 동일한 세션이 잠금을 다시 획득하더라도 sequencer는 오래된(stale) 요청을 감지할 수 있습니다. 마찬가지로 세션이 무효화되면 해당 LockIndex에 해당하는 Session은 비어 있게 됩니다.

명확히 하자면, 이 잠금 시스템은 순전히 조언적(advisory)입니다. 클라이언트가 작업을 수행하기 위해 잠금을 획득해야 한다는 강제는 없습니다. 클라이언트는 해당 잠금을 소유하지 않고도 키를 읽고, 쓰고, 삭제할 수 있습니다. 잘못된 동작을 하는 클라이언트로부터 보호하는 것은 Consul의 목표가 아닙니다.

리더 선출 (Leader Election)

세션에서 제공하는 프리미티브와 KV 저장소의 잠금 메커니즘을 사용하여 클라이언트 측 리더 선출 알고리즘을 구축할 수 있습니다. 이에 대한 자세한 내용은 리더 선출 가이드 [/consul/docs/automate/application-leader-election]에서 다룹니다.

Prepared Query 통합 (Prepared Query Integration)

Prepared query는 세션에 연결될 수 있으며, 세션이 무효화되면 prepared query가 자동으로 삭제됩니다.

더 알아보기 (Learn more)