Design Unique ID Generation For Distributed System
유일 ID를 위해 관계형 데이터베이스의 auto_increment 베이스를 기본 키를 사용하는 방법도 존재한다.
하지만 이 방법은 트래픽이 매우 높으면 값 생성 부하가 생길 수 있고, 분산 시스템 환경에서 사용하기 적절하지 않다.
- 데이터베이스 한 대인 경우: 유일한 데이터베이스 서버에 장애가 발생하면 단일 지점 장애가 발생하여 ID 할당 자체가 중단될 수 있다.
- 데이터베이스 여러 대인 경우: 각 데이터베이스에서 생성된 ID가 겹치지 않도록 보장하기 위해 지연이 발생할 수 있다.
분산 환경에서 유일 ID 생성 시스템을 설계할 때 다음의 요구사항에 맞춰 설계해 볼 수 있다.
- 유일성
- 숫자로만 구성
- 64비트로 표현 가능
- 발급 날짜에 따른 정렬 가능
- 초당 10,000개 발급 가능
유일 ID 생성 방법
Section titled “유일 ID 생성 방법”유일 ID 생성하는 방법은 여러 가지가 존재한다.
- 다중 마스터 복제(Multi-Master Replication)
- 데이터베이스의 auto_increment 기능을 활용하여 1만큼 증가 시키는 것이 아닌, k만큼 증가 시키는 방법(k=데이터 베이스 서버 수)
- 유일성 보장
- 시간에 따른 정렬 불가능 / 규모 확장 어려움
- UUIDv4
- 서버에서 생성하기 때문에 데이터베이스에 생성 부하가 발생하지 않음
- 정렬된 값으로 생성되지 않기 때문에 데이터 추가 및 삭제 시 성능 저하(클러스터형 인덱스)
- 36글자 문자열로 구성되어(바이너리 변환 시 16바이트) 저장 공간이 큼
- 유일성 보장 / 서버 사이 조율이 필요 없어 동기화 이슈 X / 규모 확장 용이
- 문자가 포함 됨 / 발급 날짜에 따른 정렬이 불가능
- UUIDv7
- 앞자리에 타임스탬프가 들어가 시간 기준 정렬된 순서로 생성 가능
- 정렬된 값으로 생성되기 때문에 클러스터형 인덱스에 적합
- 여전히 36글자 문자열로 구성되어 저장 공간이 큼(규모가 작은 곳에선 문제 없으나, 해당 경우엔 자동 증가 값을 사용해도 무방)
- 티켓 서버
- auto_increment 기능을 갖춘 데이터베이스 서버를 중앙 집중형으로 별도로 두어 ID를 생성하도록 하는 방법
- 유일성 보장 / 쉬운 구현
- SPOF(Single Point of Failure) 문제 발생(여러 티켓 서버 구축 필요 -> 동기화 이슈 발생 가능)
- 스노우플레이크 접근법
- 여러 섹션으로 분할 된 64비트 ID를 생성하는 방법
- 1비트: 사인 비트 / 41비트: 타임스탬프 / 10비트: 장비 고유 번호 / 12비트: 일련번호
- 유일성 보장 / 발급 날짜에 따른 정렬 가능 / 규모 확장 용이
- 노드 ID 충돌 문제 발생 가능
- 여러 섹션으로 분할 된 64비트 ID를 생성하는 방법
여러 방법 중 요구 사항을 만족하는 방법은 스노우플레이크 접근법을 사용할 수 있다.
각 비트 별로 상세 설명은 다음과 같다.
- 타임스탬프: 가장 많은 비트를 차지하며, 시간 기반으로 정렬 가능하도록 하는 역할
- 41비트의 길이는 밀리초로 환산 했을 때 69년간 사용 가능
- 서비스 기원 시각을 기준으로 시작하여 오버플로 발생 시점을 늦출 수 있음
- 69년 시간이 지나면 기원 시각을 바꾸거나 다른 ID 체계로 변경 필요
- 장비 고유 번호: 시스템 시작 시 결정
- 5비트: 데이터 센터 ID / 5비트: 서버 ID 식으로 할당할 수 있음
- 일반적으로 시스템 운영 중에는 변경되지 않음(잘못 변경 시 충돌 발생 가능)
- 일련번호: 같은 밀리초 동안 하나 이상의 ID를 만들어 낸 경우만 0보다 큰 값으로 증가(최대 4096개)
추가 고려 사항
Section titled “추가 고려 사항”- 시계 동기화(clock synchronization): 각 서버가 완벽히 같은 시간을 바라보지 않기 때문에 서버 간 시계가 동기화 방법 필요
- 섹션 길이 최적화: 동시성이 낮고 수명이 긴 서비스인 경우 타임스탬프 절의 길이를 늘리고 일련번호 길이를 줄이는 방법을 고려할 수 있음