Twitter Snowflake ID Generator: Struktur & Implementasi Kode

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

  1. Penentuan Epoch: Tentukan titik waktu awal (custom epoch) yang konstan agar kapasitas bit timestamp dapat bertahan lama. Twitter menggunakan milidetik sejak November 2010.
  2. Alokasi Node: Pastikan setiap instance server atau container memiliki kombinasi datacenterId dan workerId yang unik di dalam jaringan klaster untuk menghindari benturan ID.
  3. 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.