7. Designing a Unique ID Generator for Distributed Systems

분산 시스템을 위한 유일 ID 생성기 설계

1단계: 문제 이해 및 설계 범위 확정

분산 시스템에서 고유한 ID를 생성하는 문제는 매우 중요한 문제 중 하나이다. 고유 ID는 데이터베이스 레코드, 메시지, 트랜잭션 등 다양한 요소를 식별하는 데 사용된다. 특히, 여러 개의 노드가 병렬로 작업을 수행하는 분산 시스템에서는 각 노드에서 생성된 ID가 중복되지 않도록 보장하는 것이 필수적이다.

먼저 문제를 정의하자. 분산 시스템에서 고유한 ID를 생성하는 요구사항은 다음과 같다:

  1. 전역 고유성(Global Uniqueness): 생성된 ID는 시스템 내에서 절대 중복되지 않아야 한다.

  2. 고가용성(High Availability): ID 생성기는 시스템의 장애에 영향을 받지 않고 지속적으로 동작해야 한다.

  3. 고성능(High Performance): ID는 대규모 시스템에서 성능 병목 없이 빠르게 생성되어야 한다.

  4. 순서 보장(Ordering) (선택 사항): 특정 시나리오에서는 생성된 ID가 순서대로 증가하는 것이 필요할 수 있다.

이러한 요구사항을 충족시키기 위해, 여러 가지 설계 접근 방식을 고려할 수 있다. 그러나 시스템의 특성, 예산, 복잡도 등에 따라 적절한 방법을 선택하는 것이 중요하다.

2단계: 개략적 설계안 제시 및 동의 구하기

고유 ID 생성기를 설계할 때, 여러 가지 접근 방법이 있다. 각 방법은 장단점이 있으며, 시스템의 요구사항에 따라 적합한 방법을 선택해야 한다.

2.1 다중 마스터 복제

Multi-Master Replication

다중 마스터 복제는 여러 데이터베이스 인스턴스가 동시에 데이터를 기록하고 복제하는 방식이다. 각 마스터 인스턴스는 독립적으로 ID를 생성할 수 있으며, 고유성을 유지하기 위해 특정 범위나 접두사를 할당받아 사용할 수 있다.

각 데이터베이스 서버가 1씩 증가시키지 않고, 사용중인 데이터베이스 수만큼 곱한 값을 증가시킨다.

  • 장점:

    • 고가용성을 제공하며, 마스터 노드 간의 부하 분산이 가능하다.

    • 복잡한 동기화 메커니즘을 구현하지 않아도 된다.

  • 단점:

    • 마스터 간의 데이터 충돌을 방지하기 위한 추가적인 조치가 필요하다.

    • 각 마스터 노드의 ID 생성 범위를 관리해야 하는 복잡성이 있다.

2.2 UUID

UUID (Universally Unique Identifier)

UUID는 128비트 크기의 고유 식별자이다. 주로 자바에서 java.util.UUID 클래스를 통해 생성할 수 있다. UUID는 시간, 공간, 하드웨어 주소 등 여러 요소를 결합하여 고유한 값을 생성한다.

  • 장점:

    • 고유성 보장이 매우 높다.

    • 분산 시스템에서 별도의 동기화 없이도 사용 가능하다.

  • 단점:

    • 생성된 ID가 크기 때문에 저장과 전송에 비용이 들 수 있다.

    • 순서가 없으며, 특정 패턴을 가지지 않는다.

2.3 티켓 서버

Ticket Server

티켓 서버는 하나의 중앙 서버에서 일련번호를 생성하고, 각 클라이언트는 필요할 때마다 이 서버에 요청을 보내 ID를 받아간다. 이 방법은 중앙 집중식 방식으로 동작한다.

단일 데이터베이스 서버를 사용하거나, 다중 데이터베이스 앞에 프록시 서버가 생성한다.

  • 장점:

    • ID의 순서성을 보장할 수 있다.

    • 관리와 모니터링이 상대적으로 쉽다.

  • 단점:

    • 중앙 서버에 부하가 집중되며, 서버 장애 시 ID 생성에 문제가 발생할 수 있다.

    • 확장성에 한계가 있다.

2.4 트위터 스노플레이크 접근법

Twitter Snowflake Approach

트위터에서 개발한 스노플레이크는 분산 환경에서 고유 ID를 생성하는 데 사용되는 알고리즘이다. 64비트 크기의 ID는 타임스탬프, 데이터 센터 ID, 머신 ID, 일련번호로 구성된다.

  • 사인(Sign) 비트: 1비트를 할당한다. 현재 구현에서는 사용되지 않지만, 미래에 확장 가능성을 고려해 남겨두었다. 양수와 음수를 구별하는 데 사용할 수 있다.

  • 타임스탬프(Timestamp): 41비트를 할당한다. 타임스탬프는 기원 시간(epoch) 이후로 몇 밀리초(ms)가 경과했는지를 나타내는 값이다. 본 설계에서는 트위터 스노플레이크 구현에서 사용하는 기원 시간인 값 1288834974657 (2010년 11월 4일, 01:42:54 UTC) 을 기원 시간으로 사용한다.

  • 데이터센터 ID: 5비트를 할당한다. 이 필드는 32개의 데이터센터를 지원할 수 있도록 설계되었다. 데이터센터 간의 고유성을 보장하기 위해 사용된다.

  • 서버 ID: 5비트를 할당한다. 이 필드는 각 데이터센터 내에서 32개의 서버를 식별할 수 있다. 서버 간의 고유성을 보장하기 위해 사용된다.

  • 일련번호(Sequence Number): 12비트를 할당한다. 일련번호는 같은 밀리초 내에서 생성된 ID를 구분하는 역할을 한다. 서버가 ID를 생성할 때마다 이 값이 1씩 증가한다. 만약 1밀리초가 경과하면, 일련번호는 0으로 초기화(reset)된다.

  • 장점:

    • 고유성, 순서성, 성능을 모두 만족할 수 있다.

    • 확장성이 우수하며, 장애에 강하다.

  • 단점:

    • 시스템 구현이 비교적 복잡하다.

    • 타임스탬프에 대한 시간 동기화가 필요하다.

3단계: 상세 설계

각 접근 방법에 대해 기본적인 이해가 이루어진 후, 시스템 요구사항에 따라 상세 설계를 진행해야 한다. 여기서는 트위터 스노플레이크 접근법을 기반으로 한 고유 ID 생성기를 설계해 보겠다.

3.1 타임스탬프

Timestamp

스노플레이크에서 타임스탬프는 41비트로, 1밀리초 단위로 표현된다. 이는 약 69년 동안의 시간을 표현할 수 있는 범위이다. 타임스탬프는 생성 시점의 시간 정보를 포함하며, 생성된 ID의 순서를 보장하는 데 사용된다.

  • 장점:

    • 타임스탬프를 통해 ID가 생성된 시간을 알 수 있다.

    • ID가 순차적으로 생성되므로, 정렬과 검색에서 유리하다.

  • 단점:

    • 시간 동기화에 문제가 발생할 경우, ID의 순서가 왜곡될 수 있다.

3.2 일련번호

Sequence Number

일련번호는 12비트로, 같은 밀리초 내에서 생성된 ID를 구분하는 데 사용된다. 타임스탬프가 동일할 때, 일련번호가 증가하면서 고유한 ID를 생성한다. 일련번호의 최대 값은 4095로, 1밀리초 동안 최대 4096개의 ID를 생성할 수 있다.

  • 장점:

    • 밀리초 단위로 많은 수의 ID를 생성할 수 있다.

    • 타임스탬프와 조합하여, 고유성과 순서를 모두 보장한다.

  • 단점:

    • 매우 빠른 속도로 ID를 생성하는 시스템에서는 일련번호의 범위를 초과할 수 있다.

4단계: 마무리

고유 ID 생성기는 분산 시스템에서 필수적인 컴포넌트이다. 다양한 방법을 고려하여 시스템에 맞는 설계를 선택하는 것이 중요하며, 각 방법의 장단점을 신중히 평가해야 한다. 특히, 스노플레이크와 같은 접근법은 고유성, 성능, 확장성 모두를 만족하는 솔루션으로 널리 사용되고 있다. 최종 설계에서는 구현의 복잡성, 유지 보수 용이성, 장애 대응 전략 등을 종합적으로 고려해야 한다.

Last updated