‘채번’은 경우에 따라 간단하지만 그렇지 않을수도 있습니다. 단일 서버에서는 (예를 들어 AUTOINCREMENT 같은 기능으로) 키값을 순차적으로 증가시킬 수 있습니다. 하지만 만약 대규모 분산 시스템이라면 어떨까요? 반드시 순차적으로 커질까요? 값이 겹치는 경우가 있진 않을까요?
이 문제를 해결하고자 발급 서버를 둔다면 이 때 생기는 레이턴시는 어떨까요. SPOF 문제 방지를 위한 HA도 추가적으로 구성해야합니다. 따라서 트위터는 이런 문제를 해결하고자 부분적으로 Sequential함을 포기한 해답을 내놓았습니다. 이것이 바로 Snowflake 입니다.
얼마전 우리의 API 리스트에서 우린 트윗에 사용되는 유일한 ID 숫자값을 생성하는 방식을 변경할 것이라고 발표했습니다.
이 변경을 진행하기에 아직 준비가 완벽하진 않지만, 이러한 ID를 생성하기 위한 내부 서비스인 Snowflake를 만드는 작업에 박차를 가하고 있습니다. 우리가 사용하는 기술을 모든 사람들이 익숙해지고 이것이 트위터 플랫폼을 구축하는 모든 사람들에게 어떤 영향을 미치는지 알려주기 위해 우린 스노우플레이크의 코드베이스를 오늘부터 오픈 소스화하기로 결정했습니다.
진행하기 전 몇 가지 컨텍스트를 전달드리겠습니다.
우리는 온라인 데이터의 대부분을 MySQL을 사용해 저장하고 있습니다. 처음엔 데이터가 하나의 작은 데이터베이스 인스턴스에 있었지만, 시간이 지나며 점점 거대한 데이터베이스 인스턴스에 저장되게 되었고, 결국 많은 수의 거대한 데이터베이스 클러스터들에 저장되게 바뀌었습니다. 여러 가지 이유로 이러한 시스템 중 많은 부분을 카사드라 분산 데이터베이스 혹은 gizzard를 사용하는 수평 샤딩된 MySQL로 교체하기 위해 노력하고 있습니다.
MySQL과는 다르게 카산드라 DB는 (반드시 있어야 하는 건 아니지만) 고유한 ID값을 생성하는 기본 기능이 제공되지 않습니다. 따라서 카산드라 DB의 크기가 흥미로워지는 때부터 이는 ID를 위한 맞춤 솔루션을 제공하는 것이 어려워졌습니다. 샤딩된 MySQ도 마찬가지였죠.
이 시스템에 대한 우리의 요구사항은 실로 간단했습니다. 아래와 같습니다.
우린 1초에 1만개씩 생성되는 ID들을 처리할 수 있는 고성능을 갖는 무엇인가를 필요로 했습니다. 이건 자연스럽게 우릴 uncoordinated(?)한 접근 방식으로 이끌었습니다.
ID들은 이들은 러프하게라도 정렬이 되어야 했습니다. 만약 A 트윗과 B 트윗이 동시에 게시되었을 때, 이들은 다른 하나와 근접한 값들을 갖고 있어야 합니다. 우리와 트위터 고객들이 트윗들을 그렇게 정렬하기 때문이죠.
추가적으로 이 숫자들은 64비트 크기 안으로 맞춰져야 합니다. 예전에 트윗 아이디들을 저장하는 비트 사이즈를 증가시키기 위한 작업을 아주 고통스럽게 진행했습니다. 100,000개의 각기 다른 코드 베이스가 개입된 경우 당연하게도 너무 고통스러운 일입니다.
우린 몇 가지 접근법들을 고려해봤습니다. flickr가 사용했었던 MySQL 기반 티켓 서버가 있었지만, 이는 우리에게 재동기화 루틴을 구축하지 않고는 정렬을 보장하지 못했습니다. 또한 다양한 UUID들도 고려해봤지만, 이런 모든 스키마는 128비트가 필요했습니다. 주키퍼의 시퀀셜 노드들을 살펴보기도 했지만, 우리에게 필요한 성능 부분을 만족하지 못했으며 접근 방식이 실제 이점이 없음에도 가용성을 떨어뜨릴 수 있다는 점을 우려했습니다.