"가상 면접 사례로 배우는 대규모 시스템 설계 기초"를 읽고 정리한 글입니다 :)
단일 서버, 단일 스레드에서 Unique ID를 만드는 것은 아주 간단하다. 그러나 분산 시스템에서 Unique ID를 생성하는 것은 유일성을 보장하면서 성능을 같이 생각해야하기에 조금 더 생각할 점이 많다. 분산 시스템에서 유일성이 보장되는 ID를 만드는 방법은 여러가지인데, 해당 책에서는 아래와 같은 선택지들을 소개한다.
다중 마스터 복제(Multi-Master Replication)는 데이터베이스의 auto_increment 기능을 활용한다. auto_increment 기능으로 ID 값은 증가시키며 유니크한 ID를 얻는데, 이때 ID를 1만큼 증가시키는 것이 아니라 k만큼 증가시킨다. 여기서 k는 현재 사용 중인 데이터베이스 서버의 개수이다. 해당 방식으로 Unique ID를 만들면 유일성을 보장하면서, 데이터베이스의 수를 늘려 성능 역시 같이 챙겨갈 수 있다.
하지만 쉽게 유추가능한 중대한 단점들이 있는데, 우선 데이터베이스 서버의 수를 늘리거나 삭제하기가 어렵다. k 값이 변경되면 각각의 데이터베이스가 유지하고있는 increment 정보를 잘 조정하는 것이 쉬운 일이 아닐 것이다. 다른 단점으로는 ID의 값이 시간 흐름에 맞춰 커지도록 보장할 수 없다. 생성되는 ID의 값이 시간흐름에 맞추어 커질 경우 얻는 이점이 여럿 있다. 하지만, 해당 방식으로 Unique ID를 만들 경우 각각의 데이터베이스 서버마다 각자의 기준을 가지기에 시간의 흐름에 맞추어 값이 커지는 것이 보장되지 않는다.
UUID (Universally Unique Identifier)는 컴퓨터 시스템에 저장되는 정보를 유일하게 식별하기 위한 128비트짜리 수이다. UUID 값은 중복이 발생할 확률이 지극히 적기에 안전하다. 또한, UUID는 다른 서버들간의 조율 없이 독립적으로 생성이 가능하다. 즉, 동기화 이슈가 없고 달리 말하면 성능상으로 이점을 가져간다. 또한, 각각의 서버마다 별도의 ID 생성기를 둘 수 있기에 규모 확장이 쉽다.
다만 이 역시 몇가지 단점이 존재한다. 우선 ID가 128비트로 길다. 또한 ID를 시간순으로 정렬할 수 없다. 이전 섹션에서 말했던 것처럼 ID의 값이 시간 흐름에 맞추어 커질 경우 얻는 이점이 여럿 있는데, UUID의 경우 이러한 혜택을 얻을 수 없다. 마지막으로 ID 값에 숫자가 아닌 값이 포함될 수도 있다는 점이다. 이것은 결국 ID 값이 정수가 아닌 문자열이라는 뜻이고, 이로 인해 고려해야할 점이 추가될 것이다.
티켓 서버(Ticket Server)는 Unique ID를 반환해주는 하나의 티켓 서버를 사용해 Unique ID를 생성하는 방식이다. 티켓 서버를 구현하는 가장 간단한 방법은 auto_increment 기능을 갖춘 데이터베이스 서버를 사용하는 것이다. 여러 개의 웹 API 서버는 티켓 서버를 통해 유니크한 ID를 받아서 사용할 수 있으며, 하나의 중앙 집중형 티켓 서버를 사용하기에 시간순으로 정렬될 수 있다는 장점도 있다. 또한 구현하기도 쉽다는 것도 큰 장점 중 하나이다.
하지만 티켓 서버는 하나의 서버를 사용하기에, 티켓 서버가 SPOF(Single-Point-Of-Failure)가 된다. 즉 이 서버에 장애가 발생하면, 해당 서버를 사용하는 모든 시스템이 영향을 받는다. 이 문제를 해결하려면 티켓 서버를 여러 대 준비해야 한다. 하지만 이 경우 동기화와 같은 새로운 문제가 생긴다. 플리커에서는 SPOF를 피하면서 동기화 문제를 해결하기 위해, 티켓 서버를 2대 사용하고 하나는 홀수로만 증가하고 다른 하나는 짝수로만 증가하게 구현하였다고 한다. 다만, 이 경우 다중 마스터 복제의 경우와 마찬가지로 ID가 시간순으로 정렬됨을 보장할 수 없다.
트위터는 스노우플레이크(Snowflake)라고 부르는 독창적인 ID 생성 기법을 사용한다. 이 기법에서는 Id를 저장하기 위해 64비트를 사용하며, 이 비트의 각 부분을 여러 섹션으로 분할한다.
간단하게 설명하면 타임스탬프 + 머신 ID + 일련 번호
의 형식으로 Unique ID를 생성한다. 해당 방식을 사용할 경우 다른 서버와 통신할 필요 없이 독립적으로 ID를 생성할 수 있기에 성능과 확장성에서 이점을 가진다. 또한 타임 스탬프가 초반 비트를 차지하기 때문에 시간 순으로 ID를 정렬할 수 있다는 장점도 있다.
다만 단점이라면 ID를 저장하기 위해 64비트를 사용한다는 점인데, 이는 트위터가 매우 많은 데이터를 다루는 대형 서비스인 점이 반영된 것이기도 하다. 그러니 달리 말하면 대형 서비스에서는 이 점이 큰 단점이라고 보기는 힘들 것이다. 결국 32비트로는 데이터를 모두 표현하기엔 부족해질 것이니 말이다.
추가적인 내용은 해당 위키피디아를 참조하면 좋을 것이다.