무작위를 쓰지 않고 유일성을 구조로 얻는 방법이 있습니다. 64비트 를 칸으로 나눠 각 칸이 다른 것을 담게 하는 것입니다.
세 칸으로 나눈다
같은 순간에 같은 값이 나올 수 없는 이유가 구조에 있습니다.
시각이 다르면 ID 가 다르다
시각이 같으면 노드 번호가 다르다
시각과 노드가 같으면 순번이 다르다
세 칸 중 하나라도 다르면 ID가 다릅니다. 확률이 아니라 규칙으로 유일성을 얻습니다. 그리고 시각이 맨 앞에 있으므로 값이 시간순으로 커집니다.
각 칸의 폭이 정하는 것
| 칸 | 폭 | 정하는 상한 |
|---|---|---|
| 시각 | 41비트 | 밀리초를 담아 약 69년 |
| 노드 번호 | 10비트 | 발급기 1,024대 |
| 순번 | 12비트 | 한 노드가 같은 밀리초에 4,096개 |
요구사항과 대조합니다. 수명 30년 는 69년 안에 들어오고, 발급기 64대 는 1,024대에 여유가 큽니다. 발급량 초당 10만 을 64대 로 나누면 노드당 초당 1,562개이므로 밀리초당 2개면 충분합니다.
어느 칸도 부족하지 않고, 남는 여유가 어디에 있는지도 분명합니다. 이렇게 대조하는 것이 폭을 정하는 방법입니다.
폭을 옮기면 무엇이 바뀌나
칸의 합이 정해져 있으므로 한 칸을 늘리면 다른 칸이 줄어듭니다.
| 바꾸면 | 얻는 것 | 잃는 것 |
|---|---|---|
| 시각을 줄인다 | 노드나 순번이 늘어난다 | 수명이 짧아진다 |
| 노드를 줄인다 | 순번이 늘어난다 | 발급기 대수 상한이 낮아진다 |
| 순번을 줄인다 | 노드가 늘어난다 | 밀리초당 발급량 상한이 낮아진다 |
이 표가 이 설계의 전부입니다. 요구사항의 숫자를 넣으면 폭이 정해지고, 폭을 정하면 상한이 정해집니다.
시각의 기준점을 옮긴다
시각을 1970년부터 세면 41비트가 이미 많이 소모돼 남은 수명이 짧습니다. 서비스를 시작한 날을 기준점으로 잡으면 41비트를 처음부터 쓸 수 있어 69년을 온전히 얻습니다.
기준점은 어딘가에 적어 두어야 합니다. 그것을 잃으면 ID에서 시각을 되돌릴 수 없고, 새 발급기가 다른 기준점을 쓰면 시간순 정렬이 어긋납니다.
순번이 넘칠 때
같은 밀리초에 4,096개를 넘게 요청하면 순번이 부족합니다. 그때 선택은 둘입니다.
| 선택 | 결과 |
|---|---|
| 다음 밀리초까지 기다린다 | 지연이 조금 늘고 유일성이 지켜진다 |
| 순번을 돌려 다시 쓴다 | 중복이 생긴다 |
기다리는 쪽이 유일한 정답입니다. 유일성은 절대 포기하지 않는다고 정했기 때문입니다. 다만 그 대기가 예산 1ms 안에 있어야 하므로, 순번 칸을 넉넉히 두는 것이 대기를 드물게 만드는 방법입니다.