Pernyataan Masalah dan Kapan Masalah Ini Berlaku
Rancang generator ID unik terdistribusi di empat region. Setiap region memiliki paling banyak 200 generator worker. Seluruh armada mencapai puncak 2 juta ID per detik, sementara satu worker mana pun dapat menghasilkan hingga 3.000 ID dalam satu milidetik. Setiap ID harus berupa integer 64-bit positif, unik secara global, secara kasar berurutan berdasarkan waktu pembuatan, dan dapat digunakan setidaknya selama 60 tahun. Hot path tidak boleh melakukan permintaan jaringan untuk setiap ID. Target latensi adalah p99 pada atau di bawah 5 milidetik dan target ketersediaan adalah 99,99%, tetapi generator harus berhenti daripada mengambil risiko membuat duplikat.
Adanya celah (gaps) diizinkan, dan urutan monotonik yang ketat di seluruh region tidak diperlukan. ID ini merupakan pengidentifikasi pesan internal dan primary key database, sehingga prediktabilitas dapat diterima untuk saat ini. Penanganan terpisah diperlukan jika pengidentifikasi akan diekspos ke klien yang tidak tepercaya. Kapasitas dan SLO ini adalah batasan wawancara, bukan klaim tentang lalu lintas produksi perusahaan mana pun.
Pertanyaan ini cocok untuk wawancara senior backend, infrastruktur, dan perancangan sistem. Tugas sebenarnya adalah mengubah masa pakai, jumlah worker, dan persyaratan lonjakan milidetik menjadi anggaran bit, lalu membuktikan bahwa kegagalan jam, konkurensi, dan identitas worker tidak dapat membuat duplikat. Hanya mengatakan "gunakan Snowflake" bukanlah sebuah desain.
Apa yang Sedang Dievaluasi oleh Pewawancara
Pertama, dapatkah kandidat membedakan keunikan, pengurutan, kontinuitas, dan ketidakpastian? Snowflake dapat menyediakan integer 64-bit yang unik dan secara kasar berurutan berdasarkan waktu. Snowflake tidak secara otomatis menyediakan sequence tanpa celah, urutan kausal di seluruh region, atau token keamanan. Persyaratan yang berbeda akan mengubah desain.
Kedua, dapatkah kandidat menurunkan tata letak bit dari batasan yang ada? Jawaban yang kuat menghitung apa yang dicakup oleh 41 bit timestamp, 10 bit worker, dan 12 bit sequence, lalu memeriksa masa pakai 60 tahun, 800 worker, dan 3.000 ID per worker per milidetik. Jawaban tersebut tidak menyalin pembagian klasik lalu mencari pembenarannya setelahnya.
Ketiga, dapatkah kandidat membuktikan bahwa ID tidak berulang? Kebenaran membutuhkan satu pemilik aktif untuk sebuah kode worker dalam rentang waktu yang tumpang tindih, tidak ada penggunaan kembali sequence oleh worker tersebut dalam satu milidetik, dan tidak ada rollback atau restart jam yang masuk kembali ke rentang timestamp dan sequence yang telah digunakan sebelumnya.
Keempat, dapatkah kandidat menyelesaikan desain penanganan kegagalan? Kehabisan sequence, jam mundur, sewa (lease) yang hilang, proses yang hidup kembali (resurrected processes), isolasi regional, dan kehabisan timestamp semuanya dapat mengancam keunikan atau ketersediaan. Jawabannya membutuhkan kondisi henti (stop conditions), peringatan, dan prosedur pemulihan yang eksplisit.
Kelima, dapatkah kandidat memilih antara Snowflake, UUIDv7, UUID acak, dan alokasi terpusat atau segmen berdasarkan batasan? Persyaratan 64-bit dan ketiadaan koordinasi per-ID menguntungkan Snowflake di sini. Jika 128 bit dapat diterima dan pendaftaran worker tidak diinginkan, UUIDv7 akan menjadi kandidat yang lebih sederhana.
Pertanyaan untuk Diklarifikasi Sebelum Menjawab
- Apakah keunikan bersifat deterministik, atau probabilitas tabrakan (collision) yang kecil dapat diterima? Keunikan deterministik membutuhkan namespace worker yang terisolasi. Jika keunikan probabilistik dapat diterima, UUIDv4 atau UUIDv7 dapat menghilangkan alokasi worker.
- Haruskah pengidentifikasi berukuran 64 bit? Jika database, protokol, dan indeks menerima 128 bit, standar UUIDv7 menawarkan awalan waktu dan ruang acak dengan control plane yang lebih sederhana. Masalah ini menetapkan output harus berupa integer 64-bit positif.
- Seberapa kuat "keterurutan" yang dibutuhkan? Urutan waktu kasar dapat menggunakan jam lokal. Urutan total yang ketat di seluruh region memerlukan sequencer terpusat, log konsensus, atau sequence yang dipartisi berdasarkan bisnis dan memiliki biaya yang sangat berbeda.
- Apakah celah (gaps) diizinkan? Pra-alokasi segmen, crash, dan percobaan ulang dapat meninggalkan celah. Menggabungkan ketiadaan celah dengan peningkatan global yang ketat akan memindahkan alokasi ke jalur transaksi serial. Celah diizinkan di sini.
- Apakah ID akan bersifat publik? Bit timestamp dan worker dapat mengungkapkan waktu pembuatan dan informasi deployment, sedangkan nilai yang bertambah dapat dihitung secara berurutan (enumerated). Hal itu mungkin dapat diterima untuk key internal; pengidentifikasi publik harus menggunakan nilai buram (opaque) yang terpisah.
- Bagaimana worker dibuat dan diganti? Mesin tetap, kontainer yang diorkestrasi, dan autoscaling memiliki risiko penggunaan ulang identitas worker yang berbeda. Worker dinamis membutuhkan sewa (lease), fencing, dan aturan penggunaan ulang yang aman.
- Apa yang diprioritaskan saat terjadi partisi jaringan? Worker yang ada dapat melanjutkan tugasnya selama control plane regional mereka sehat dan sewa mereka tetap aman. Seorang worker harus berhenti jika kepemilikan eksklusif tidak dapat dibuktikan, mengorbankan sebagian ketersediaan.
Jawaban 30 Detik
"Saya akan membagi 64 bit menjadi satu bit tanda tetap, 41 bit waktu milidetik, 10 bit untuk region ditambah worker, dan 12 bit sequence per milidetik. Ini mencakup sekitar 69,7 tahun, 1.024 kode worker, dan 4.096 ID per worker per milidetik, sehingga memenuhi batasan. Setiap worker menghasilkan (timestamp, worker, sequence) di dalam critical section lokal, tanpa panggilan jaringan pada hot path. Control plane regional mengalokasikan dan memperbarui sewa worker. Worker tidak pernah memutar ulang sequence saat habis (wrap) dan berhenti jika kehilangan sewa atau terjadi rollback jam yang tidak aman. Hasilnya secara kasar terurut berdasarkan waktu, tidak terurut secara ketat di seluruh region. Jika 128 bit diizinkan dan saya ingin menghilangkan pendaftaran worker, saya akan mengevaluasi UUIDv7."
Pembahasan Mendalam Langkah demi Langkah
Langkah 1: Gunakan batasan untuk menolak opsi default yang tidak sesuai
Sequence database terpusat memberikan pengurutan yang jelas, tetapi setiap alokasi memasuki jalur penulisan bersama. Hal itu bertentangan dengan persyaratan hot path tanpa jaringan dan isolasi regional. Mengalokasikan rentang secara berkelompok (batch) mengamortisasi koordinasi tetapi meninggalkan celah saat worker mengalami crash. Celah diizinkan, jadi alokasi segmen tetap menjadi alternatif yang layak, meskipun masih memerlukan layanan rentang dan kebijakan prefetch.
UUIDv4 dan UUIDv7 keduanya berformat 128-bit. UUIDv4 bersifat acak dan tidak menyediakan pengurutan waktu. Berdasarkan RFC 9562, UUIDv7 menempatkan timestamp milidetik Unix 48-bit di bagian paling signifikan dan menggunakan ruang yang tersisa untuk versi, varian, dan field acak atau monotonik. Format ini dapat menghasilkan nilai yang terurut secara kasar tanpa mendaftarkan worker, tetapi melanggar persyaratan 64-bit dari masalah ini.
Hal ini menyisakan tata letak 64-bit bergaya Snowflake. "Bebas koordinasi" hanya berlaku untuk setiap alokasi pada hot path; identitas worker masih membutuhkan control plane. Menyembunyikan biaya tersebut tidak membuat sistem benar-benar bebas dari koordinasi.
Langkah 2: Turunkan tata letak 1 + 41 + 10 + 12 dari kapasitas
Cadangkan bit paling signifikan (MSB) sebagai nol agar nilainya tetap berupa integer 64-bit bertanda positif, lalu alokasikan 63 bit yang tersisa sebagai berikut:
| Field | Bit | Rentang | Kesesuaian dengan persyaratan |
|---|---|---|---|
| Tanda (Sign) | 1 | Tetap pada 0 | Menjaga BIGINT tetap positif |
| Milidetik sejak custom epoch | 41 | 2^41 milidetik, sekitar 69,7 tahun | Melebihi masa pakai 60 tahun |
| Region + worker | 10 | 1.024 kode | 2 bit region × 8 bit worker lokal mendukung 4 × 256 worker |
| Sequence dalam satu milidetik | 12 | 0–4.095, atau 4.096 nilai | Melebihi 3.000 ID per worker per milidetik |
Totalnya adalah 1 + 41 + 10 + 12 = 64 bit. Armada memiliki paling banyak 4 × 200 = 800 worker, di bawah 1.024, dan 200 worker per region muat dalam 256 nilai yang disediakan oleh 8 bit. Rentang waktu 41-bit adalah sekitar 2^41 ÷ 1000 ÷ 60 ÷ 60 ÷ 24 ÷ 365.2425 = 69.7 tahun. Untuk memenuhi syarat "positif" secara ketat, cadangkan ID bernilai semua-nol dan tempatkan custom epoch sebelum alokasi pertama. Bahkan sequence nol pada worker pertama tidak akan pernah menghasilkan 0.
Tingkat beban seluruh armada sebesar 2 juta ID per detik adalah pemeriksaan kapasitas agregat. Field sequence harus memenuhi lonjakan per-worker per-milidetik yang lebih tajam. Perhitungan rata-rata per detik tidak dapat membuktikan bahwa 12 bit sudah cukup: satu worker tetap dapat menghabiskan sequence-nya meskipun QPS seluruh armada rendah.
Langkah 3: Terapkan pembuatan lokal dan buktikan keunikannya
Setiap worker menggunakan operasi integer 64-bit dan melindungi lastMs serta sequence dengan kunci (lock) atau atomic critical section:
nextId():
lock
now = wallClockMs() - customEpochMs
if now < lastMs:
fail("clock_moved_back")
if now == lastMs:
if sequence == 4095:
now = waitUntilAfter(lastMs)
sequence = 0
else:
sequence = sequence + 1
else:
sequence = 0
lastMs = now
return (now << 22) | (workerCode << 12) | sequenceSequence tidak boleh secara diam-diam kembali ke nol (wrap) setelah 4.095 saat jam masih berada di milidetik yang sama; hal itu akan langsung menduplikasi nilai sebelumnya. ID ke-4.096 valid karena sequence dimulai dari nol. Permintaan ke-4.097 dalam milidetik yang sama harus menunggu milidetik berikutnya atau menerima error beban berlebih (overload).
Pembuktian keunikan memiliki tiga kasus. Worker yang berbeda memiliki kode worker 10-bit yang berbeda. Worker yang sama pada milidetik yang berbeda memiliki timestamp 41-bit yang berbeda. Worker yang sama pada milidetik yang sama memiliki nilai sequence 12-bit yang berbeda. Jika field tetap berada dalam rentang, kepemilikan worker tidak tumpang tindih, dan jam tidak pernah masuk kembali ke status yang telah digunakan, muatan 63-bit penuh tidak dapat berulang.
Langkah 4: Tempatkan identitas worker di control plane
Jalankan alokator sewa worker independen di setiap region, sambil menetapkan kode 2-bit region melalui konfigurasi deployment. Control plane menyimpan:
| Field | Tujuan |
|---|---|
region_id, worker_id | Membentuk kode worker global 10-bit |
owner_id | Mengidentifikasi proses saat ini atau instans deployment |
fencing_token | Membedakan pemilik yang lebih baru dan lebih lama dari satu kode worker |
lease_expires_at | Membatasi berapa lama kepemilikan tetap valid |
timestamp_ceiling_ms | Membatasi rentang timestamp yang boleh digunakan pemilik lama selama penggunaan ulang yang aman |
Saat startup, sebuah node memperoleh ID worker dan sewa. Hot path ID hanya memeriksa status pemilik, status fencing, batas waktu keamanan sewa dalam memori, dan now <= timestamp_ceiling_ms; pembaruan terjadi secara asinkron, sehingga alokasi tidak menghubungi control plane untuk setiap ID. Sebuah node berhenti menghasilkan ID segera setelah sewanya tidak aman atau mencapai batas atas timestamp. Sebelum menggunakan kembali ID worker tersebut untuk pengganti, control plane harus memblokir (fence) pemilik lama dan menunggu sampai jam node baru melampaui timestamp_ceiling_ms milik sewa lama. Dengan demikian, node lama yang tertunda dan penggantinya tidak dapat menggunakan rentang timestamp yang sama.
Fencing token tidak dienkode ke dalam ID akhir, sehingga tidak dapat memperbaiki tabrakan setelah tabrakan terjadi. Token ini mencegah pemilik basi (stale) masuk ke jalur pembuatan. Jika sebuah platform tidak dapat memblokir proses lama secara andal, platform tersebut harus menetapkan ID worker yang berumur panjang dan tidak digunakan ulang ke slot deployment atau menggunakan UUIDv7 daripada berpura-pura bahwa sewa saja dapat menyelesaikan masalah proses yang hidup kembali.
Langkah 5: Tentukan kondisi henti untuk jam, overflow, dan partisi
Kebijakan untuk now < lastMs harus dibatasi. Salah satu contohnya adalah menunggu rollback paling lama 5 milidetik hanya jika permintaan memiliki anggaran latensi yang cukup; waktu tunggu tersebut diperhitungkan dalam anggaran p99 5 milidetik. Untuk rollback yang lebih besar atau sisa anggaran tidak mencukupi, kembalikan retryable error, hapus node dari layanan, dan beri peringatan (alert). Saat proses startup, bandingkan waktu saat ini dengan high-water mark persisten untuk worker tersebut dan tolak untuk memulai jika jam tertinggal. Menyimpan lastMs hanya di memori tidak mencakup kejadian restart.
Ketika sequence habis, tunggu hingga milidetik berikutnya dan tambahkan metrik sequence_exhausted. Kehabisan sequence yang sering terjadi berarti beban tidak seimbang atau anggaran bit salah. Distribusikan lalu lintas, tambahkan worker, atau alokasikan lebih banyak bit sequence dalam format baru. Jangan pernah melakukan wrap.
Selama isolasi antar region atau dari jaringan global, field region 2-bit masih memisahkan namespace. Worker yang ada dapat melanjutkan secara lokal selama sewa regional mereka tetap aman. Jika layanan sewa regional tidak tersedia dan batas waktu keamanan kedaluwarsa, worker tersebut berhenti. Keunikan lebih diprioritaskan daripada target ketersediaan 99,99%, dan pengecualian tersebut harus didokumentasikan dalam SLO dan peringatan.
Timestamp 41-bit pada akhirnya akan kedaluwarsa. Tampilkan sisa masa pakai epoch dan mulailah migrasi beberapa tahun sebelumnya. Jangan pernah mereset timestamp setelah overflow atau secara diam-diam menafsirkan ulang kolom 64-bit yang sama dengan tata letak baru. Menambahkan region atau memperluas jumlah worker memerlukan jenis migrasi format yang sama.
Langkah 6: Nyatakan apa arti sebenarnya dari "terurut" dan "aman"
Menempatkan waktu pada bit tinggi membuat ID terurut secara kasar, tetapi clock skew dapat menyebabkan catatan yang dibuat lebih baru memiliki ID yang lebih kecil. Bit worker juga memengaruhi pengurutan di dalam satu milidetik. ID Snowflake tidak membuktikan kausalitas antar region dan tidak dapat menggantikan sequence commit buku besar pembayaran.
Jika API melakukan sinkronisasi bertahap dengan id > cursor, ID yang datang terlambat dari jam yang lambat mungkin lebih kecil daripada kursor yang disimpan dan akan terlewati selamanya. Jika pengurutan lengkap penting, gunakan sequence commit database, posisi log konsensus, atau sequencer yang dicakupkan pada partisi bisnis seperti percakapan atau akun. Snowflake tetap menjadi identitas, bukan otoritas pengurutan.
ID mentah juga mengekspos perkiraan waktu pembuatan dan dapat mengungkapkan bit region atau worker. ID ini bukan kredensial otorisasi. Sumber daya publik dapat mempertahankan key internal 64-bit dan mengekspos pengidentifikasi buram (opaque) independen. Jangan pernah mengandalkan ID yang sulit ditebak untuk melindungi data.
Langkah 7: Bandingkan alternatif di bawah batasan yang sama
| Pendekatan | Lebar dan urutan | Koordinasi | Paling cocok untuk | Biaya utama |
|---|---|---|---|---|
| Gaya Snowflake | 64-bit, terurut kasar | Koordinasi saat startup dan pembaruan; hot path lokal | ID 64-bit, throughput sangat tinggi, urutan perkiraan | Manajemen jam dan worker |
| UUIDv7 | 128-bit, berawalan waktu | Tanpa pendaftaran worker | 128 bit dapat diterima dan format standar tanpa control plane worker lebih disukai | Nilai lebih lebar; keunikan bergantung pada kualitas keacakan dan implementasi |
| UUIDv4 | 128-bit, urutan acak | Tidak ada | Pengurutan tidak diperlukan dan sifat buram penting | Lokalitas indeks lebih buruk dan tidak ada inferensi waktu dari ID |
| Sequencer terpusat / segmen | Biasanya 64-bit, meningkat ketat atau kasar | Alokasikan melalui layanan atau database; segmen dapat dibatch | Pengurutan terpusat diperlukan atau sistem sudah bergantung pada database | Ketergantungan jaringan/database; batch meninggalkan celah |
Snowflake memenangkan masalah ini karena batasan ketat 64-bit dan larangan panggilan jaringan per-ID. Jika pewawancara menghapus batasan 64-bit, pertimbangkan kembali UUIDv7. Jika urutan total yang ketat diperlukan, akui bahwa Snowflake tidak memenuhinya dan beralihlah ke sequencer serial daripada memaksakan primitif yang salah.
Langkah 8: Validasi dengan failure injection
Validasi harus melampaui sekadar menghasilkan sampel normal dalam jumlah besar tanpa duplikat. Tangani setidaknya kasus-kasus berikut:
- Bekukan waktu dan hasilkan 4.096 ID dari satu worker dalam satu milidetik. Semuanya harus unik; ID ke-4.097 harus menunggu atau gagal.
- Panggil satu generator secara bersamaan (konkuren) dan verifikasi bahwa critical section lokal mencegah dua thread menggunakan kembali sebuah sequence.
- Putar mundur jam sebesar 1, 5, dan 2.000 milidetik dan verifikasi jalur tunggu, batas waktu (timeout), penghapusan node, dan peringatan.
- Jeda pemilik lama, biarkan sewanya kedaluwarsa, aktifkan pemilik baru, lalu lanjutkan pemilik lama. Verifikasi bahwa fencing mencegah proses basi menghasilkan ID.
- Bekukan keempat region dan seluruh 800 worker pada milidetik yang sama, lalu hasilkan sequence yang berbeda dan verifikasi rentang field yang didekodekan serta keunikan global.
- Isolasikan layanan sewa regional. Worker yang ada dapat melanjutkan dalam interval sewa yang aman dan harus fail-closed setelahnya.
- Majukan waktu ke
2^41 - 1dan verifikasi bahwa milidetik berikutnya ditolak dan memicu peringatan migrasi.
Minimal, pemantauan produksi harus mencakup clock_rollback_ms, sequence_exhausted, kegagalan pembaruan sewa, ruang kode worker yang tersedia, latensi pembuatan, tingkat error, dan sisa masa pakai epoch. Batasan unik pada database adalah garis pertahanan terakhir dan sumber peringatan yang berguna, tetapi menangkap tabrakan dan mencoba lagi bukanlah pengganti kebenaran generator.
Contoh Jawaban Berkualitas Tinggi
"Pertama-tama saya akan mengonfirmasi bahwa persyaratannya adalah ID 64-bit positif yang unik secara deterministik. Celah diizinkan, dan pengurutan hanya perlu perkiraan. Dengan empat region, 200 worker per region, dan hingga 3.000 ID per worker per milidetik, saya akan memilih desain bergaya Snowflake daripada UUIDv7 128-bit atau panggilan sequencer terpusat untuk setiap ID.
Bit paling signifikan tetap nol. Timestamp milidetik custom epoch 41-bit bertahan sekitar 69,7 tahun. Sepuluh bit worker dibagi menjadi 2 bit region dan 8 bit worker lokal, mencakup 4 × 256 node. Sequence 12-bit menghasilkan 4.096 nilai per worker per milidetik. Ketiga dimensi tersebut melebihi batasan yang dinyatakan dan menggunakan tepat 63-bit muatan.
Setiap worker menyimpan lastMs dan sequence dalam critical section lokal. Worker mereset sequence saat waktu bertambah, menaikkannya dalam milidetik yang sama, dan menunggu setelah sequence 4.095. Worker tidak pernah melanjutkan jika jam mundur: waktu tunggu hingga 5 milidetik diperbolehkan dalam batas anggaran latensi, sedangkan rollback yang lebih besar akan menghapus worker dari layanan dan memicu peringatan. Kode worker yang berbeda memisahkan worker, timestamp memisahkan milidetik untuk satu worker, dan sequence memisahkan ID dalam satu worker-milidetik.
Saya akan menjalankan control plane sewa worker regional. Node hanya menghubunginya saat startup dan untuk pembaruan asinkron, sementara pembuatan ID tetap bersifat lokal. Pemilik lama berhenti setelah kehilangan sewanya. Sebelum menggunakan kembali ID worker tersebut, alokator memblokir (fences) pemilik lama dan memastikan jam node pengganti telah melampaui batas atas timestamp sewa lama. Jika kepemilikan eksklusif tidak dapat dibuktikan, worker berhenti.
Terakhir, saya akan menyatakan bahwa ini hanya memberikan urutan perkiraan. Urutan ketat di seluruh region memerlukan log konsensus atau sequencer yang dipartisi berdasarkan bisnis, dan ID publik yang tidak dapat dihitung secara berurutan memerlukan nilai buram terpisah. Validasi akan mencakup permintaan ke-4.097 dalam satu milidetik, akses sequence konkuren, rollback jam dua detik, pengambilalihan sewa, dan habisnya masa pakai epoch—bukan hanya happy path."
Kesalahan Umum
- Langsung mengatakan "gunakan UUID" → Jawaban tidak pernah mengklarifikasi lebar bit, urutan, atau semantik tabrakan → Pisahkan UUIDv4, UUIDv7, dan namespace worker deterministik terlebih dahulu.
- Menyalin 41-10-12 begitu saja → Tidak ada bukti bahwa masa pakai, worker, atau kapasitas lonjakan sesuai → Hitung
2^41milidetik,2^10kode worker, dan2^12nilai sequence secara terpisah. - Hanya menggunakan QPS rata-rata armada → Lonjakan per-worker per-milidetik masih dapat menghabiskan sequence → Validasi kapasitas pada unit waktu terkecil dan worker terpadat.
- Melakukan wrap pada sequence dengan mask → Worker yang sama mengulang ID dalam milidetik yang sama → Tunggu milidetik berikutnya, terapkan backpressure, atau gagalkan.
- Menempatkan ID worker dalam konfigurasi dan berhenti di situ → Autoscaling, konfigurasi yang disalin, dan proses yang hidup kembali menciptakan dua pemilik → Rancang sewa, fencing, penggunaan ulang yang aman, dan kondisi henti.
- Melanjutkan dengan wall clock saat ini setelah rollback → Worker dapat mengulangi pasangan timestamp dan sequence → Tunggu dalam batas tertentu atau lakukan fail-closed, dan periksa high-water mark persisten setelah restart.
- Menyebut urutan kasar sebagai monotonik global → Clock skew dan worker konkuren mengubah urutan → Gunakan log serial atau partitioned sequencer jika urutan ketat diperlukan.
- Memperlakukan ID sebagai kontrol akses → ID yang dapat didekodekan atau dihitung secara berurutan tidak mengotorisasi permintaan → Ekspos pengidentifikasi buram terpisah dan tetap tegakkan otorisasi di sisi server.
- Hanya menguji jutaan ID normal → Beban acak biasa jarang mencapai batasan berbahaya → Bekukan waktu dan lakukan injeksi rollback, pengambilalihan sewa, dan kehabisan field.
Pertanyaan Lanjutan dan Jawabannya
Lanjutan 1: Apa yang berubah jika ID harus bertambah secara ketat di seluruh region tanpa celah?
Snowflake tidak lagi memenuhi syarat. Urutan total yang ketat mengharuskan setiap alokasi melewati titik linearisasi, seperti status sequence tunggal dalam log konsensus. Ketiadaan celah juga berarti nomor tersebut harus dicomit bersama dengan transaksi bisnis yang berhasil, sehingga segmen yang diambil sebelumnya (prefetched) dan tidak terpakai tidak dapat diterima. Sisi minoritas dari partisi jaringan harus berhenti, mengurangi throughput, ketersediaan, dan meningkatkan latensi. Tanyakan apakah bisnis benar-benar membutuhkan ketiadaan celah; banyak sistem audit membutuhkan referensi bisnis yang tidak dapat diubah (immutable), bukan primary key database tanpa celah.
Lanjutan 2: Bagaimana Anda menambahkan region kelima atau mendukung 300 worker per region?
2 bit region dan 8 bit worker lokal saat ini tidak dapat merepresentasikan kedua kasus tersebut. Sebelum peluncuran, 10 bit tersebut dapat dipartisi ulang dengan menambahkan bit region dan mengurangi kapasitas worker lokal. Setelah ID mulai dibuat, nilai-nilai lama tidak dapat ditafsirkan ulang secara online di bawah batas baru. Perkenalkan format baru secara eksplisit atau bermigrasi ke pengidentifikasi 128-bit, dengan reader dan writer yang mengenali kedua versi. Memindahkan batas bit secara diam-diam akan merusak asumsi decoding, pengurutan, dan keunikan.
Lanjutan 3: Jam node mundur dua detik. Bisakah bit sequence membuatnya tetap tersedia?
Tidak aman jika menggunakan solusi sementara yang tidak disimpan. Setelah restart, proses mungkin lupa timestamp logis mana yang telah dipinjamnya. Di bawah kebijakan yang dinyatakan, segera hapus node dari layanan, beri peringatan, dan alihkan lalu lintas ke tempat lain. Pulihkan hanya setelah wall time mengejar ketinggalan hingga lastMs atau setelah memulihkan waktu logis yang terbukti dari high-water mark persisten. Jika ketersediaan saat terjadi rollback adalah wajib, gunakan desain jam logis yang persisten dan buktikan kembali perilaku overflow, restart, dan pengurutannya; hanya mengatakan "gunakan jam logis" mengabaikan masalah pemulihan status yang sulit.
Lanjutan 4: ID akan muncul di URL pesanan publik. Bagaimana Anda mencegah enumerasi dan kebocoran volume penjualan?
Pertahankan Snowflake sebagai join key internal dan buat pengidentifikasi eksternal acak yang terpisah. UUIDv4 cocok jika diinginkan entropi dan sifat buram yang memadai; UUIDv7 adalah opsi jika membocorkan awalan waktu dapat diterima. Simpan pemetaannya pada baris pesanan. Setiap operasi pembacaan pesanan harus tetap mengotorisasi pengguna saat ini, terlepas dari format pengidentifikasinya. Ketidakpastian mengurangi risiko enumerasi tetapi tidak menggantikan otorisasi.
Lanjutan 5: Bisakah pembuatan ID berlanjut saat sebuah region kehilangan kontak dengan control plane global?
Ya, karena bit region mengisolasi namespace dan alokasi tidak memerlukan control plane global. Worker yang ada terus berjalan selama sewa regional mereka tetap berada dalam interval yang aman. Jika alokator sewa regional juga tidak tersedia, worker yang batas waktu pembaruannya kedaluwarsa akan berhenti. Penyimpanan sewa regional itu sendiri dapat menggunakan klaster konsensus di dalam region untuk ketersediaan, tetapi dua partisi tidak boleh memperbarui kode worker yang sama secara bersamaan.
Lanjutan 6: Bagaimana jika satu worker tiba-tiba membutuhkan 5.000 ID per milidetik?
Sequence 12-bit hanya menyediakan 4.096 nilai. Respons langsungnya adalah menerapkan backpressure dan mendistribusikan beban ke lebih banyak worker; melakukan wrap dilarang keras. Untuk jangka panjang, alokasikan lebih banyak bit sequence dalam format baru dengan mengambilnya dari masa pakai timestamp atau kapasitas worker, atau hapus batasan 64-bit dan gunakan UUIDv7. Ukur distribusi lonjakan satu milidetik yang sebenarnya sebelum mengubah tata letak; rata-rata per detik tidak menjawab pertanyaan ini.
Lanjutan 7: Jika urutan ketat hanya diperlukan dalam satu percakapan, apakah sequencer global diperlukan?
Tidak. Petakan setiap percakapan ke partisi yang stabil dan pertahankan sequence commit di dalam partisi tersebut. Snowflake tetap menjadi identitas global, sementara sequence partisi membawa urutan percakapan. Ini mengurangi koordinasi dan domain kegagalan dibandingkan dengan melakukan serialisasi pada semua region. Reader mengurutkan berdasarkan (conversation_id, sequence) dan tidak pernah mengasumsikan ID Snowflake sama dengan urutan commit percakapan.