UUID üreteci
UUID'ler üretin — rastgele v4 veya zamana göre sıralı v7 — teker teker ya da toplu olarak.
122 rastgele bit. Ne zaman oluşturulduğu hakkında hiçbir şey açığa çıkarmaz.
Üretiliyor…
UUID nedir ve neden vardır
Bir UUID — Universally Unique Identifier (Evrensel Benzersiz Tanımlayıcı), Microsoft belgelerinde GUID de denir — tanıdık 8-4-4-4-12 gruplamasında 32 on altılık basamak olarak yazılan 128 bitlik bir değerdir. Tüm amacı, ayrı sistemlerin, aralarında hiçbir eşgüdüm olmadan bağımsızca tanımlayıcılar üretmesine ve yine de sonuçların çakışmayacağından emin olmasına olanak tanımaktır. Onu bir veritabanı otomatik artan sütunundan farklı kılan budur: iki sunucu, bir uçakta çevrimdışı iki mobil istemci ve bir artalan işi, kimseden izin istemeden aynı anda kayıtlar oluşturabilir.
Buradaki benzersizlik garantili değil, olasılıksaldır. Sürüm 4, 122 biti rastgeleliğe bırakır; bu, milyarlarca değer üretmenin bile bir tekrar olasılığını, verinin bunun yerine bir diskte sessizce bozulması olasılığının çok altında bıraktığı kadar büyük bir alandır. Pratikte onu benzersiz olarak ele alabilirsiniz; matematik zayıf halka değildir.
Sürüm 4 ve sürüm 7 — önemli olan seçim
Sürüm 4 baştan sona rastgeledir. Hiçbir bilgi taşımaz: ne zaman yapıldığını değil, kim tarafından değil, hangi sırada değil. Bu, onu nereye koyduğunuza bağlı olarak ya en büyük gücü ya da temel kusurudur.
2024'te RFC 9562'de standartlaştırılan sürüm 7, ilk 48 biti bir milisaniye Unix zaman damgasıyla değiştirir ve geri kalanı rastgelelikle doldurur. Zaman önce geldiği ve değer soldan sağa okunduğu için, v7 tanımlayıcılarını düz metin olarak sıralamak onları kronolojik olarak da sıralar.
Bu görsel bir fark değildir. Veritabanları birincil anahtarları sıralı bir B-ağacı dizininde tutar. v7 anahtarları ekleyin, her yeni satır ağacın sağ kenarına, bir öncekinin yanına düşer — yazdığınız sayfalar bellekte kalır ve dizin düzenli büyür. v4 anahtarları ekleyin, her yazma rastgele bir konuma düşer; böylece veritabanı her seferinde farklı bir sayfaya dokunur, önbellek isabet oranları düşer ve dizin parçalanır. Büyük, yoğun bir tabloda ekleme veriminde fark önemlidir; v7'nin birincil anahtarlar için bu kadar hızlı benimsenmesinin nedeni budur.
- Veritabanı birincil anahtarları, olay ve günlük tanımlayıcıları ve oluşturulma zamanına göre sıralamak ya da aralık sorgusu yapmak isteyeceğiniz her şey için v7 seçin.
- Tanımlayıcı güvenilmez bir yerde göründüğünde ve hiçbir şey — bir kaydın diğerinden hemen önce oluşturulduğu gerçeği dahil — sızdırmaması gerektiğinde v4 seçin.
- Sıralamanın önemli olmadığı bir ilinti kimliği (correlation ID), bir idempotency anahtarı ya da bir dosya adı için ikisi de uygundur.
Ödünleşim tam da o sızıntıdır: bir v7 tanımlayıcısı, onu görene, milisaniyesine kadar, ne zaman oluşturulduğunu söyler. Bir satır kimliği için bu genellikle zararsız ve çoğu zaman yararlıdır. Bir parola sıfırlama token'ı ya da genel bir paylaşım bağlantısı için ise yayımlamayı düşünmediğiniz bir bilgidir — ve bunlar hiç UUID olmamalı, özel bir sır üretecinden rastgele token'lar olmalıdır.
Aynı milisaniye içinde sıralama
Birçok v7 uygulamasını yakalayan bir incelik: modern donanım milisaniye başına birden çok tanımlayıcı üretir. İki değer bir zaman damgasını paylaşırsa, sıraları ardından gelen rastgele bitlerle belirlenir — yani rastgele. Sıkı bir döngüde elli tane üretin, yalnızca kabaca sıralı elli değer alırsınız ve tam da v7'yi seçme nedeniniz olan özelliği yitirirsiniz.
RFC 9562 bunu monoton bir sayaçla ele alır ve bu araç onu uygular: zaman damgasının hemen ardındaki 12 bit bir milisaniye içinde yukarı doğru sayar; böylece bir parti yaklaşık değil, kesin biçimde artar. Sayaç dolarsa — aynı milisaniyede 4096'dan çok değer — üreteç, kaydırıp öncülünden önce sıralanan bir değer yaymak yerine bir sonraki milisaniyeyi ödünç alır. NTP düzeltmeleriyle gerçekleşen, saatin geriye gitmesini de aynı şekilde ele alır.
Bir v7 değerini soldan sağa okumak, örnek olarak 0190a1b2-c3d4-7e5f-8a9b-0c1d2e3f4a5b'yi alarak:
- 0190a1b2-c3d4 — milisaniye cinsinden 48 bitlik Unix zaman damgası. Önce geldiği için metin sırası zaman sırasıdır.
- 7 — sürüm nibble'ı; bunu bir v4 değil, bir v7 yapan şey.
- e5f — 12 bitlik monoton sayaç; tek bir milisaniye içinde artan.
- 8 — varyant bitleri; RFC 9562 tarafından her modern UUID için sabitlenmiş (her zaman 8, 9, a ya da b).
- a9b-0c1d2e3f4a5b — kalan 62 bit, tümüyle rastgele.
UUID'leri saklama ve kullanma
Standart biçim, tireli küçük harftir ve RFC 9562, üreteçlerin tam olarak bunu yaymasını söyler — bu araç bu yüzden hiçbir biçimlendirme seçeneği sunmaz. Yine de başka yazımlarla karşılaşacaksınız: Microsoft araçlarında büyük harfli ve süslü parantez içinde ve birinin daha kısa bir sütun istediği yerde tirelerden arındırılmış. Hepsi aynı 128 bittir ve karşılaştırmalar büyük/küçük harfe duyarsız olmalıdır.
Önemli olan yer saklamadır. Bir UUID 16 bayttır, ama metin biçimi 36 karakterdir — dolayısıyla onu bir dize olarak saklamak, satırdaki ve daha önemlisi onu içeren her dizindeki alanı iki katından fazla artırır. Bir tane varsa yerel bir tür kullanın:
uuid -- PostgreSQL: native 16-byte type BINARY(16) -- MySQL: compact; CHAR(36) wastes 20 bytes/row uniqueidentifier -- SQL Server crypto.randomUUID() // JavaScript: v4 only, needs a secure context uuid.uuid4() / uuid7() # Python: stdlib v4; v7 via a library
Son bir uyarı: bir UUID tanımlar, yetkilendirmez. Tahmin edilemez oldukları için, birini içeren listelenmemiş bir URL'yi özel saymak caziptir. Ama tanımlayıcılar sızar — günlükler, tarayıcı geçmişi, yönlendiren başlıkları ve ekran görüntüleri aracılığıyla — dolayısıyla gerçekten korunması gereken herhangi bir şeyin arkasında hâlâ gerçek bir izin denetimi olması gerekir.
Sıkça sorulan sorular
- v4 mü v7 mi kullanmalıyım?
- Veritabanı birincil anahtarları ve oluşturulma zamanına göre sıralayacağınız her şey için v7 kullanın: baştaki zaman damgası, eklemeleri dizine dağıtmak yerine sonunda kümelenmiş tutar. Bir tanımlayıcı, ne zaman oluşturulduğu dahil hiçbir şeyi açığa çıkarmaması gerektiğinde v4 kullanın.
- İki UUID hiç aynı olur mu?
- Mümkündür ama yok denecek kadar olası değildir. Sürüm 4'ün 122 rastgele biti vardır; bu yüzden milyarlarca değer üretildikten sonra bile bir çakışma olasılığı, depolamanın onları bunun yerine sessizce bozması olasılığının çok altında kalır.
- Sürüm 1, 3 ve 5'e ne oldu?
- Sürüm 1, bir zaman damgasını ve makinenin MAC adresini kodlar; bu, donanım kimliğini sızdırır ve bir tarayıcıda hiç üretilemez. Sürüm 3 ve 5, bir UUID'yi bir ad alanı ve bir addan MD5 ya da SHA-1 kullanarak deterministik olarak türetir — aynı girdinin her zaman aynı tanımlayıcıyı üretmesi gerektiğinde yararlıdır, ama yeni bir tane üretmekten farklı bir iştir.
- Bir UUID, gizli bir token olarak kullanılacak kadar güvenli mi?
- Bir v4 UUID tahmin edilemezdir, ama bir v7 UUID oluşturulma zamanını açıkça kodlar ve hiçbiri bir kimlik bilgisi olarak tasarlanmamıştır. Parola sıfırlamaları, oturum token'ları ya da paylaşım bağlantıları için, tanımlayıcının tahmin edilmesinin zor olmasına güvenmek yerine özel bir rastgele sır üretin ve sunucuda izinleri denetleyin.
- v7 partim neden başka araçlarda kusursuz sıralı değil?
- Çünkü birçok uygulama monoton sayacı atlar. Birkaç değer bir milisaniyeyi paylaştığında, sıraları ardından gelen rastgele bitlere düşer. Bu araç RFC 9562'nin sayacını uygular; böylece burada üretilen bir parti kesin biçimde artar.
- Bir UUID'yi bir veritabanında nasıl saklamalıyım?
- Bir tane varsa yerel 16 baytlık bir türde — PostgreSQL'de uuid, SQL Server'da uniqueidentifier, MySQL'de BINARY(16). Bunun yerine 36 karakterlik metin biçimini saklamak, satırdaki ve sütunu içeren her dizindeki alanı iki katından fazla artırır.
- Bunlar sizin sunucularınızda mı üretiliyor?
- Hayır. Platformun kriptografik rastgele kaynağı olan crypto.getRandomValues kullanılarak tarayıcınızda üretilir — crypto.randomUUID'nin kullandığının aynısı. Hiçbir değer hiçbir yere gönderilmez ve sayfayı yeniden yüklemek tümüyle yeni bir küme üretir.