Twitter Snowflake adalah algoritma pembuatan ID unik terdistribusi 64-bit yang menghasilkan identifikasi waktu secara kronologis tanpa koordinasi pusat antar node. ID ini dirancang untuk mengatasi hambatan pembuatan kunci primer berbasis auto-increment pada basis data relasional dalam sistem berskala masif dengan tingkat penulisan tinggi.
Setiap ID Snowflake terdiri dari kombinasi komponen waktu, identifikasi mesin (datacenter dan worker ID), serta nomor urut (sequence) dalam milidetik yang sama. Struktur bit ini memastikan keunikan global sekaligus menjaga keterurutan waktu pembuatan data secara alami.
Struktur Bit Twitter Snowflake ID
Panjang total ID adalah 64 bit (setara dengan sebuah bilangan bulat bertanda 64-bit / long pada banyak bahasa pemrograman). Berikut adalah rincian alokasi bitnya:
| Komponen Bit | Jumlah Bit | Deskripsi Fungsi |
|---|---|---|
| Sign Bit | 1 bit | Selalu bernilai 0 untuk menjaga agar ID selalu bernilai positif. |
| Timestamp | 41 bit | Selisih waktu (dalam milidetik) terhadap custom epoch yang ditentukan. Mendukung hingga ~69 tahun. |
| Datacenter ID | 5 bit | Identifikasi pusat data tempat node beroperasi (mendukung hingga 32 datacenter). |
| Worker ID | 5 bit | Identifikasi mesin/proses spesifik dalam datacenter (mendukung hingga 32 worker per datacenter). |
| Sequence | 12 bit | Nomor urut inkremental untuk setiap ID yang dibuat dalam milidetik yang sama (maksimal 4096 ID per milidetik per worker). |
Implementasi Kode Generator (Go)
Berikut adalah implementasi dasar algoritma Snowflake menggunakan bahasa pemrograman Go dengan penanganan dasar untuk clock drift dan sequence overflow.
package main
import (
"errors"
"sync"
"time"
)
const (
epoch = int64(1288834974657) // Custom epoch (Twitter snowflake epoch)
workerIdBits = uint(5)
datacenterBits = uint(5)
sequenceBits = uint(12)
maxWorkerId = -1 ^ (-1 << workerIdBits)
maxDatacenter = -1 ^ (-1 << datacenterBits)
workerIdShift = sequenceBits
datacenterShift = sequenceBits + workerIdBits
timestampShift = sequenceBits + workerIdBits + datacenterBits
sequenceMask = -1 ^ (-1 << sequenceBits)
)
type Snowflake struct {
mu sync.Mutex
timestamp int64
workerId int64
datacenterId int64
sequence int64
}
func NewSnowflake(workerId int64, datacenterId int64) (*Snowflake, error) {
if workerId > maxWorkerId || workerId < 0 {
return nil, errors.New("worker ID out of range")
}
if datacenterId > maxDatacenter || datacenterId < 0 {
return nil, errors.New("datacenter ID out of range")
}
return &Snowflake{
timestamp: 0,
workerId: workerId,
datacenterId: datacenterId,
sequence: 0,
}, nil
}
func (s *Snowflake) NextID() (int64, error) {
s.mu.Lock()
defer s.mu.Unlock()
now := time.Now().UnixNano() / int64(time.Millisecond)
if now < s.timestamp {
return 0, errors.New("clock moved backwards. Refusing to generate id")
}
if s.timestamp == now {
s.sequence = (s.sequence + 1) & sequenceMask
if s.sequence == 0 {
for now <= s.timestamp {
now = time.Now().UnixNano() / int64(time.Millisecond)
}
}
} else {
s.sequence = 0
}
s.timestamp = now
id := ((now - epoch) << timestampShift) |
(s.datacenterId << datacenterShift) |
(s.workerId << workerIdShift) |
s.sequence
return id, nil
}
Langkah-Langkah Teknis Pengoperasian
- Penentuan Epoch: Tentukan titik waktu awal (custom epoch) yang konstan agar kapasitas bit timestamp dapat bertahan lama. Twitter menggunakan milidetik sejak November 2010.
- Alokasi Node: Pastikan setiap instance server atau container memiliki kombinasi
datacenterIddanworkerIdyang unik di dalam jaringan klaster untuk menghindari benturan ID. - Sinkronisasi Waktu (NTP): Gunakan protokol NTP (Network Time Protocol) yang ketat pada semua server. Pergeseran waktu mundur (clock drift) dapat memicu error atau duplikasi ID jika tidak ditangani dengan validasi penolakan.
Troubleshooting Lapangan
Kendala utama dalam implementasi Snowflake adalah perubahan waktu sistem (clock skew). Jika server mengalami sinkronisasi waktu mundur, generator harus menolak pembuatan ID baru sampai waktu sistem melewati timestamp terakhir yang tercatat. Untuk skala sangat masif, pendekatan berbasis Redis atau koordinasi ZooKeeper sering digunakan untuk manajemen alokasi worker ID secara dinamis.