Snowflake형 ID는 시간·소유자·같은 시간 안의 순번을 조합해 분산 생성 비용을 낮추는 형식입니다. 유일성, 시간 정렬, commit 순서, 재시도 멱등성은 서로 다른 보장이므로 비트 배치만 보고 운영 계약을 추론하면 안 됩니다.
세 필드 조합과 ID 중복
시간·node ID·단위 시간 안 sequence를 결합하는 ID는 세 필드 조합이 유일해야 합니다.
예를 들어 같은 1ms에 node=7이 sequence 0, 1을 만들면 ID는 서로 다르지만, sequence 0으로 발급된 ID가 먼저라는 사실은 해당 거래가 먼저 commit됐다는 뜻이 아닙니다. 요청 재시도는 같은 논리 요청 키를 유지해야 하며, 새 ID를 매번 만들면 저장소에는 유일한 두 행이 남을 수 있습니다. 따라서 생성기 테스트와 업무 멱등성 테스트를 분리합니다. 노드 두 개가 같은 ID를 쓰거나 시계가 뒤로 가 이전 시간의 sequence를 다시 시작하면 충돌할 수 있습니다. 알고리즘 이름이 재시작·클라우드 중복 배치를 자동으로 해결하지 않습니다.
예시로 양의 64비트 표현에서 시간 41bit·노드 10bit·순번 12bit를 사용한다고 합시다. 이는 흔한 모형의 한 예이며 제품마다 실제 배치는 다릅니다.
| 필드 | 예제 범위 | 조건 |
|---|---|---|
| 시간 41bit, 1ms 단위 | 2^41 ms, 약 69.7년 | 기준 epoch·종료 시점·역행 정책 |
| node 10bit | 1024개 ID | 동시에 같은 ID 소유 금지 |
| sequence 12bit | 0~4095 | 같은 ms에 wrap 금지 |
이 예에서는 41+10+12=63비트이므로 node와 sequence를 합친 22비트를 시간 필드 뒤로 밀어 ((time-epoch) << 22) | (node << 12) | sequence로 결합합니다. 생성 전에 time-epoch가 41bit, node가 10bit, sequence가 12bit 범위에 들어오는지 확인하고 overflow나 부호 비트를 조용히 잘라내지 않습니다. 이 비트 배치가 정하는 단위 시간별 생성 한도는 로컬 한도일 뿐이며, 전체 throughput이나 지연은 별도 문제입니다.
Sequence 포화와 다음 시간 대기·거절
같은 ms에 4096개를 만든 뒤 다음 ID를 0으로 wrap하면 이전 조합과 충돌합니다. 다음 유효 시간까지 제한적으로 기다리거나 실패하거나 검증된 논리 시간 정책을 사용합니다. 대기 자체에 deadline·메모리 상한이 필요합니다. 무한 busy-spin으로 CPU를 소모하지 않습니다.
그림을 글로 읽기
- 유효한 node ID 소유 확인
- 현재 시간·이전 시간 비교
- 같은 시간의 순번 확보
- 범위 확인 후 bit 결합
- 유효한 node ID 소유 확인 → 현재 시간·이전 시간 비교: 생성 권한
- 현재 시간·이전 시간 비교 → 같은 시간의 순번 확보: 역행 정책 적용
- 같은 시간의 순번 확보 → 범위 확인 후 bit 결합: 포화·overflow 거절
시계 역행과 가용성 정책
이전 time=1000인데 물리 시계가 990이면 그 값을 그대로 사용해 sequence를 초기화하지 않습니다. 일정 한도까지 대기·요청 거절·내구 last time 기반 논리 증가 등의 정책을 정합니다. 논리 시간을 앞으로 유지하면 ID의 시간 성분이 실제 wall time과 달라질 수 있어 표시·만료 계산에 그대로 쓰지 않습니다.
재시작 시 last time·sequence가 필요한 모델이면 그것을 잊지 않거나 안전한 새 node epoch를 확보해야 합니다. 프로세스 메모리만으로 이전 생성 이력을 보존한다고 가정하지 않습니다. 미래로 큰 점프는 비트 수명과 이후 대기에 영향을 주므로 허용 오차·운영 경보를 둡니다.
노드 ID 재할당과 옛 생성자 종료
node ID allocator가 lease를 주더라도 옛 worker가 pause 후 살아나 같은 ID로 계속 만들면 새 worker와 충돌할 수 있습니다. lease 갱신 실패 시 생성 차단·소유 세대·재사용 정책과 최종 unique 검사를 조합합니다. 임의 대기 시간 하나만으로 무한히 정지한 옛 프로세스의 종료를 증명할 수는 없습니다.
발급 서비스 장애 때 아무 node ID를 골라 계속 진행하면 유일성을 버리는 선택입니다. 신규 생성의 거절·대기·대체 ID 형식을 명시하고 외부 API와 저장소 제약을 유지합니다.
시간 정렬과 Commit 순서·멱등성의 분리
먼저 ID를 받은 거래가 나중에 commit할 수 있습니다. 노드 clock skew와 같은 시간의 node/sequence ordering도 있어 ID 대소가 전역 인과·commit 순서를 뜻하지 않습니다. 내부 페이지 배치나 대략 시각 정렬에는 유용할 수 있지만 권위 변경 version으로 대체하지 않습니다.
같은 주문 재시도마다 새 ID를 발급하면 ID는 모두 유일해도 주문은 중복됩니다. 논리 요청 키는 별도로 유지합니다. 큰 ID는 JavaScript Number와 JSON 숫자 파싱에서 정밀도를 잃을 수 있어 문자열·정확 정수 경로를 end-to-end로 사용합니다. ID가 시간·노드 정보를 노출하는지도 보안·제품 요구에 맞춰 검토합니다.
가짜 시계·노드 할당기 기반 경계 시험
정상 증가·같은 시간 포화·역행·미래 jump·동일 node ID·재시작을 작은 bit 폭으로 재현해 충돌·거절 정책을 확인합니다. DB·로그·브라우저 왕복에서 원문 ID도 대조합니다. 본문은 생성 모형 설명이며 실제 분산 ID 서비스를 배포·부하 검증한 결과는 아닙니다.