UUID v1 Üretici
Gömülü zaman damgasıyla zaman tabanlı UUID v1 oluşturur
…
Biçimle
UUID v1 Nedir?
UUID v1, RFC 4122'de (2005) standartlaştırılmış orijinal UUID sürümüdür. Oluşturan ana bilgisayarın MAC adresiyle yüksek hassasiyetli zaman damgasını birleştirerek benzersiz tanımlayıcılar üretir.
Zaman damgası gömülü olduğundan aynı ana bilgisayardan gelen UUID v1 değerleri zamanla monoton artar. Bu, her düğümün koordinasyon olmadan bağımsız UUID oluşturabileceği dağıtık sistemler için tasarlanmıştı.
Bugün UUID v1, büyük ölçüde UUID v7 (sıralanabilir, MAC sızıntısı yok) ve UUID v4 (tamamen rastgele, özel) tarafından yerini almıştır.
UUID v1 Anatomisi
550e8400-e29b-11d4-a716-446655440000 gibi bir UUID v1 dizesi altı farklı alan kodlar:
| Alan | Boyut | Açıklama |
|---|---|---|
| time_low | 32 bits | 60 bitlik Gregoryen zaman damgasının 32 bitlik düşük alanı (15 Ekim 1582'den itibaren 100 nanosaniyelik aralıklar) |
| time_mid | 16 bits | 60 bitlik zaman damgasının orta 16 bitlik alanı |
| time_hi_and_version | 16 bits | 60 bitlik zaman damgasının üst 12 biti artı 4 bitlik sürüm numarası (her zaman <code>1</code>) |
| clock_seq_hi_res | 8 bits | 2 bitlik RFC 4122 varyant işaretçisiyle birleştirilen 6 bitlik saat dizisi yüksek alanı |
| clock_seq_low | 8 bits | Saat dizisinin alt 8 biti |
| node | 48 bits | 48 bitlik düğüm tanımlayıcısı — genellikle oluşturan ağ arayüzünün MAC adresi |
Saat dizisi alanı 14 bitlik bir sayaçtır. Sistem saati geriye gittiğinde veya sistem yeniden başlatıldığında artırılır.
UUID v1 Zaman Damgasını Çözme
60 bitlik zaman damgası UUID'de üç alana dağıtılmıştır. Oluşturma zamanını yeniden oluşturmak için:
time_low(bayt 0–3),time_mid(bayt 4–5) vetime_hi'yı (bayt 6–7, sürüm nibble'ı çıkarılmış) çıkarın- Yeniden birleştirin:
(time_hi << 48) | (time_mid << 32) | time_low - Sonuç, 15 Ekim 1582'den (Gregoryen takvim dönemi) itibaren
100 nanosaniyelik aralıkların60 bitlik sayısıdır - Gregoryen-Unix farkını çıkarın: 122.192.928.000.000.000
- 100 nanosaniyelik aralıkları milisaniyeye dönüştürmek için
10.000'e bölün - Date nesnesi oluşturmak için
Unix milisaniye zaman damgasıolarak kullanın - İnsan tarafından okunabilir çıktı için
ISO 8601biçiminde biçimlendirin
Zaman damgası hassasiyeti 100 nanosaniyedir — UUID v7'nin milisaniye hassasiyetinden çok daha ince.
Gizlilik Endişeleri
UUID v1'in en önemli dezavantajı, düğüm alanında oluşturan ana bilgisayarın MAC adresini gömmesidir.
UUID v1 elde eden bir saldırgan şunları belirleyebilir: (1) ID'nin yaklaşık oluşturma zamanı, (2) oluşturan ana bilgisayarın MAC adresi ve (3) ID oluşturma hızı.
Bu nedenle UUID v1, bu bilgiyi açıklamaktan çekinmiyorsanız kamuya yönelik tanımlayıcı olarak kullanılmamalıdır.
UUID v1'in Hâlâ Uygun Olduğu Durumlar
UUID v1 ile UUID v7 Karşılaştırması
UUID v7, zaman sıralı tanımlayıcılar için UUID v1'in modern halefidir:
| Konu | UUID v1 | UUID v7 |
|---|---|---|
| Dönem / Zaman Tabanı | Gregoryen dönemi (15 Ekim 1582) | Unix dönemi (1 Ocak 1970) |
| Hassasiyet | 100 nanosaniye | 1 milisaniye |
| Düğüm Tanımlayıcısı | MAC adresi (ana bilgisayar kimliğini sızdırır) | Rastgele (özel) |
| Gizlilik | MAC adresini ve oluşturma zaman damgasını sızdırır | Gömülü ana bilgisayar bilgisi yok |
| Veritabanı dizin performansı | İyi — ana bilgisayar başına sıralı | Mükemmel — tüm oluşturucularda k-sıralanabilir |
| Standart | RFC 4122 (2005) | RFC 9562 (2024) |
Yeni projeler için UUID v7, UUID v1'in önerilen halefidir.
Kod Örnekleri
UUID v1 üretimi tarayıcılarda veya Node.js'de yerel olarak mevcut değildir. uuid npm paketini kullanın:
// Generate a UUID v1 using the Web Crypto API
function generateUuidV1() {
const buf = new Uint8Array(16)
crypto.getRandomValues(buf)
const ms = BigInt(Date.now())
const gregorianOffset = 122192928000000000n
const t = ms * 10000n + gregorianOffset
const tLow = Number(t & 0xFFFFFFFFn)
const tMid = Number((t >> 32n) & 0xFFFFn)
const tHiVer = Number((t >> 48n) & 0x0FFFn) | 0x1000 // version 1
const clockSeq = (buf[8] & 0x3F) | 0x80 // variant 10xxxxxx
const clockSeqLow = buf[9]
const hex = (n, pad) => n.toString(16).padStart(pad, '0')
const node = [...buf.slice(10)].map(b => b.toString(16).padStart(2, '0')).join('')
return `${hex(tLow,8)}-${hex(tMid,4)}-${hex(tHiVer,4)}-${hex(clockSeq,2)}${hex(clockSeqLow,2)}-${node}`
}
// Extract the embedded timestamp from a UUID v1
function extractTimestamp(uuid) {
const parts = uuid.split('-')
const tHex = parts[2].slice(1) + parts[1] + parts[0]
const t = BigInt('0x' + tHex)
const ms = (t - 122192928000000000n) / 10000n
return new Date(Number(ms))
}
const id = generateUuidV1()
console.log(id) // e.g. "1eb5e8b0-6b4d-11ee-9c45-a1f2b3c4d5e6"
console.log(extractTimestamp(id)) // e.g. 2023-10-15T12:34:56.789Zimport uuid from datetime import datetime, timezone # Generate UUID v1 (uses MAC address by default) uid = uuid.uuid1() print(uid) # Extract embedded timestamp # uuid.time is 100-ns intervals since Oct 15, 1582 GREGORIAN_OFFSET = 122192928000000000 # 100-ns intervals ts_100ns = uid.time ts_ms = (ts_100ns - GREGORIAN_OFFSET) // 10000 dt = datetime.fromtimestamp(ts_ms / 1000, tz=timezone.utc) print(dt.isoformat()) # e.g. "2023-10-15T12:34:56.789000+00:00"
package main
import (
"fmt"
"time"
"github.com/google/uuid" // go get github.com/google/uuid
)
func main() {
id, _ := uuid.NewUUID() // UUID v1
fmt.Println(id)
// Extract timestamp from UUID v1
// uuid.Time is 100-ns ticks since Oct 15, 1582
t := id.Time()
sec := int64(t)/1e7 - 12219292800 // convert to Unix seconds
nsec := (int64(t) % 1e7) * 100
ts := time.Unix(sec, nsec).UTC()
fmt.Println(ts.Format(time.RFC3339Nano))
}