SoupCalc

Snowflake ID 생성기: Twitter의 63비트 분산 식별자 내부 구조

Snowflake ID란 무엇인가?

Snowflake ID는 중앙 조정 지점 없이 분산 시스템 전반에서 고유 식별자를 생성하는 데 사용되는 63비트 정수이다. Twitter는 2010년에 샤딩된 MySQL 클러스터에 쓰기 작업을 수행하는 수십 대의 애플리케이션 서버로는 확장할 수 없는 자동 증가 데이터베이스 시퀀스를 대체하기 위해 이 형식을 개발했다. 각 Snowflake ID는 부호 있는 64비트 정수이며, 최상위 비트는 항상 0으로 유지되어 63개의 페이로드 비트가 네 개의 필드로 분할된다: 41비트 타임스탬프 오프셋, 5비트 데이터센터 식별자, 5비트 머신 식별자, 그리고 12비트 시퀀스 번호이다. 이 레이아웃을 통해 단일 Snowflake 서비스 노드는 밀리초당 최대 4,096개의 고유 ID를 생성할 수 있으며, 수백 개의 워커 프로세스로 구성된 배포 환경에서 초당 수백만 개의 ID라는 이론적 처리량을 시스템에 제공한다.

Snowflake ID는 단조 증가한다 — 동일한 에포크 내에서 각 새 ID는 이전 ID보다 크다 — 그러나 노드 간에는 엄격하게 순차적이지 않다. 동일한 밀리초 내에 작동하는 두 머신은 서로 교차 배치된 ID를 생성하게 되는데, 이는 의도적인 트레이드오프이다: 이 방식은 완벽한 순서를 희생하여 절대적인 운영 독립성을 확보한다. 각 워커는 자신의 데이터센터와 머신 번호, 그리고 현재 시간만 알면 되며, 피어나 락 서비스에 전혀 문의하지 않고도 전역적으로 고유한 식별자를 생성할 수 있다.

63비트 식별자의 구조

Snowflake ID는 최상위 비트에서 최하위 비트 순으로 다음 필드로 구성된 63비트 정수이다:

  • 41비트 타임스탬프 — 사용자 정의 에포크로부터 경과한 밀리초.
  • 5비트 데이터센터 ID — 워커를 호스팅하는 물리적 데이터센터를 식별.
  • 5비트 머신 ID — 해당 데이터센터 내의 개별 호스트 또는 프로세스를 식별.
  • 12비트 시퀀스 번호 — 클럭이 앞으로 이동할 때 0으로 재설정되는 밀리초당 카운터.

이 레이아웃을 정확히 설명하는 표현은 다음과 같다: 41비트 타임스탬프, 5비트 데이터센터, 5비트 머신, 그리고 12비트 시퀀스. 이 필드들은 함께 63비트를 차지하며, 선행 부호 비트는 0으로 설정되어 Java 및 C#과 같은 언어에서 ID가 부호 있는 64비트 정수에 편안하게 들어맞는다.

Twitter 에포크와 타임스탬프 구성 요소

모든 Snowflake ID는 사용자 정의 에포크로부터 측정된 타임스탬프 오프셋을 포함한다: 1288834974657 밀리초. 이 값은 대략 2010-11-04T04:42:54.657Z에 해당하며, Twitter의 내부 Snowflake 배포 시작 시점에 맞추기 위해 선택되었다. Unix 에포크 대신 사용자 정의 에포크를 사용하면 41비트 타임스탬프 필드가 오버플로우되기 전까지 약 69년의 범위를 표현할 수 있다. 이 필드가 보유할 수 있는 최대 타임스탬프 값은 2^41 - 1, 즉 2,199,023,255,551 밀리초이며 — 에포크 이후 약 69.7년으로, 롤오버 날짜가 2080년대까지 미뤄진다.

타임스탬프를 인코딩하려면 현재 Unix 에포크 밀리초에서 에포크를 뺀 다음, 하위 세 필드를 위한 공간을 확보하기 위해 결과를 왼쪽으로 22비트 시프트한다. 에포크보다 이른 입력 타임스탬프는 유효하지 않으며 반드시 거부되어야 한다.

데이터센터 및 머신 노드 식별

5비트 데이터센터 필드와 5비트 머신 필드는 각각 0부터 31까지의 값을 허용하며, 배포 환경 전체에서 총 1,024개의 고유 노드 식별자를 생성합니다. 워커는 시작 시점에 일반적으로 구성 파일, ZooKeeper와 같은 조정 서비스, 또는 명령줄 인수를 통해 데이터센터 ID와 머신 ID를 할당받습니다. 이 할당은 플릿 내에서 고유해야 합니다: 동일한 (데이터센터, 머신) 쌍을 공유하는 두 워커는 클럭이 어긋나지 않는 한 충돌하는 ID를 생성하게 됩니다.

이 필드들은 데이터센터 값을 17비트 왼쪽 시프트하고 머신 값을 12비트 왼쪽 시프트한 후, 시프트된 값들을 63비트 정수에 OR 연산하여 ID에 삽입됩니다. 총 노드 수 1,024개는 대부분의 실제 배포 환경에 충분하지만, 1,024개 이상의 워커가 필요한 환경에서는 시퀀스 필드나 타임스탬프 필드에서 비트를 빌려 쓸 수 있으며, 이 경우 처리량이나 에포크 범위를 희생하게 됩니다.

시퀀스 카운터와 클럭 경계

12비트 시퀀스 필드는 Snowflake 설계의 핵심 동력입니다. 이 필드는 0부터 4,095까지 실행되며 동일 밀리초 내에서 생성되는 각 ID마다 1씩 증가합니다. 시퀀스가 4,095에 도달하면 워커는 시스템 클럭이 다음 밀리초로 넘어갈 때까지 비지 루프에서 대기하며, 이 시점에 시퀀스가 0으로 재설정되고 생성이 재개됩니다. 이로 인해 단일 노드는 밀리초당 최대 4,096개의 ID 버스트 속도를 가집니다.

클럭 드리프트와 클럭 롤백은 Snowflake 알고리즘의 가장 중요한 두 가지 장애 모드입니다. 시스템 클럭이 거꾸로 이동하는 경우 — NTP 보정, 가상 머신 마이그레이션, 또는 수동 변경으로 인해 — 워커가 마지막으로 생성한 타임스탬프보다 작은 타임스탬프를 가진 ID를 생성할 수 있으며, 이는 고유성 보장을 깨뜨립니다. 표준 완화 방법은 클럭 롤백이 감지되면 ID 생성을 중단하고 오류를 발생시켜, 클럭이 마지막으로 확인된 타임스탬프를 따라잡을 때까지 요청 처리를 거부하는 것입니다. 다운타임을 허용할 수 없는 배포 환경에서는 전용 시간 서비스나 논리 클럭 계층을 고려해야 합니다.

계산 예시

다음 입력 값을 고려해 보겠습니다: Unix 에포크 타임스탬프 1700000000000밀리초, 데이터센터 ID 7, 머신 ID 13, 시퀀스 번호 4095.

인코딩. 먼저 타임스탬프 오프셋을 계산합니다: 1700000000000에서 Snowflake 에포크 1288834974657을 빼면 411165025343이 됩니다. 이 오프셋을 22비트 왼쪽 시프트하여 1724551110456246272를 얻습니다. 데이터센터 값 7을 17비트 왼쪽 시프트하여 917504를 얻습니다. 머신 값 13을 12비트 왼쪽 시프트하여 53248을 얻습니다. 시퀀스 번호는 시프트가 필요하지 않습니다. 네 항을 비트 OR로 결합하여 최종 Snowflake ID 1724551110457221119를 생성합니다.

디코딩. ID 1724551110457221119에서 원래 필드를 복원하려면, 하위 12비트를 마스킹하여 시퀀스를 추출합니다: 4095. 12비트 오른쪽 시프트 후 하위 5비트를 마스킹하여 머신 ID를 복원합니다: 13. 17비트 오른쪽 시프트 후 하위 5비트를 마스킹하여 데이터센터 ID를 복원합니다: 7. 22비트 오른쪽 시프트하여 타임스탬프 오프셋 411165025343을 얻습니다. 에포크 1288834974657을 더하여 원래 Unix 에포크 타임스탬프 1700000000000을 복원합니다.

모든 필드가 할당된 비트 너비 내에 정확히 들어맞고 인코딩 과정에서 정보가 손실되지 않기 때문에 왕복 변환은 정확합니다.

정확성 및 한계

Snowflake 인코딩 방식은 모든 입력이 유효 범위 내에 있을 경우 결정적이며 되돌릴 수 있습니다. 타임스탬프 오프셋은 0 이상의 41비트 정수여야 하며, 데이터센터 및 머신 ID는 0에서 31 사이, 시퀀스는 0에서 4,095 사이여야 합니다. 이 범위를 벗어나는 입력은 유효하지 않은 것으로 거부됩니다.

이 방식은 윤초나 밀리초 미만의 정밀도를 고려하지 않습니다. 호스트 시스템 시계에 의존하므로, 시계가 표류하거나 외부 프로세스에 의해 조정될 수 있습니다. 시스템 시계가 큰 NTP 점프로 앞당겨지는 배포 환경에서는 오프셋 필드가 올바르게 전진하지만, 시퀀스 카운터는 그 간격 동안 유휴 상태였기 때문에 발급되지 않은 ID 구간이 남게 됩니다. 이는 고유성에는 무해하지만 ID 타임라인에 불연속성을 만듭니다.

동일한 (데이터센터, 머신) 튜플을 공유하는 네트워크 파티션된 워커가 동시에 활성 상태가 되면 충돌하는 ID를 생성하게 됩니다. 식별자 공간은 1,024개의 고유 노드 슬롯을 제공하며, 이 수를 초과하려면 사용자 정의 비트 레이아웃 변형이 필요합니다.

출처

편집 기록

이 글은 Twitter의 2010년 참조 구현에서 정의된 Snowflake ID 형식을 설명합니다. 비트 레이아웃과 에포크 값은 오픈소스 Scala 소스 코드에서 직접 가져왔습니다. 예제로 제시된 계산은 동일한 값을 인코딩 및 디코딩하여 왕복을 확인하는 수동 계산으로 검증되었습니다. 시계 롤백 및 노드 제한에 관한 논의는 분산 ID 생성에 관한 엔지니어링 문헌에 문서화된 운영 경험을 반영합니다.

이 글은 비트 레이아웃을 변경한 서드파티 구현이나 변형 — 예를 들어 10비트 머신 ID, 다른 에포크, 또는 조정 서비스에서 가져온 워커 ID 필드를 사용하는 것 — 은 다루지 않습니다. 그러한 변형은 원본 Snowflake 명세의 범위를 벗어납니다. 작성자: SoupCalc 편집팀 최종 검토일: 2026년 8월 11일.