UUID 即通用唯一識別碼,是一種用于計算機系統中以確保全局唯一性的標識符。其標準定義于 RFC 4122 文檔中。標準形式包含 32 個 16 進制數字,以連字符切割為五組,格式為 8-4-4-4-12,總共 36 個字符。(形如, d169aa7f-4a6e-4ee2-b073-8e46e29c72f3)。UUID 在生成時利用到了空間信息和時間信息的唯一性,幾乎可以排除重復的可能性。并且 UUID 的生成不依賴于中央注冊機構或協調機制。所以很適合在分布式系統中使用。通常被用于數據庫中作為記錄的唯一標識、在分布式系統中唯一標識資源或服務等(例如使用 Kraft 模式啟動 Kafka 時,需要先給 Kafka 分配 UUID)。
變體
目前 UUID 常見的變體有:、變體1(RFC 4122)、變體2(Microsoft)。它們的主要差別在于二進制存儲和傳輸的方式不同,變體1采用大端序作為二進制存儲與傳輸,而變體2采用部分小端序的方式存儲與傳輸。此外,兩種變體代表變體的比特不同,即第 9 字節的高位不同(xxxxxxxx-xxxx-xxxx-Nxxx-xxxxxxxxxxxx 即此處的 N 不同),變體1為8到b,變體2為c16或d16。
其中,最常見的變體為 RFC 4122 定義的變體1。
版本
根據 RFC 4122,UUID 有五種不同的版本:
- 版本1: 基于時間和節點 ID 生成的 UUID
- 版本2: DCE 安全的 UUID
- 版本3: 通過命名空間標識符和名稱進行散列得到的 UUID,使用 MD5 散列
- 版本4: 隨機生成的 UUID
- 版本5: 通過命名空間標識符和名稱進行散列得到的 UUID,使用 SHA-1 散列
不同版本的版本號標志在 UUID 的第 7 字節處(xxxxxxxx-xxxx-Mxxx-xxxx-xxxxxxxxxxxx 即此處的 M 即為版本號)
google/uuid 生成 UUID
版本1
版本1的 UUID 根據 60 比特的時間戳和節點的 48 比特 MAC 地址(尾部 12 個字符)組成。此外還有 14 比特的時鐘序列用于擴展時間戳,以便處理處理器時鐘不能足夠快地前進的情況。剩下的 6 比特即為版本號和變體標志。(UUID 總長 128 比特)
利用 google/uuid 庫的 NewUUID 接口即可生成 RFC 版本號為1的 UUID。
示例代碼如下:
package mainimport ("fmt""github.com/google/uuid"
)func main() {// 生成一個新的 UUIDnewUUID, _ := uuid.NewUUID()fmt.Printf("Generated UUID: %s\n", newUUID)// 獲取并打印UUID的變體variant := newUUID.Variant()fmt.Printf("UUID Variant: %d\n", variant)// 獲取并打印UUID的版本version := newUUID.Version().String()fmt.Println(version)
}
版本4
版本4的 UUID 仍會使用 6 比特的空間標識版本號和變體標識,剩余的 122 比特隨機生成,故版本4可以生成 2^122 種不同的 UUID,如此龐大的隨機空間很難出現相同的 UUID,因此隨機生成的 UUID 仍然能夠提供足夠的唯一性保證。
利用 google/uuid 庫的 New 接口即可生成 RFC 版本號為4的 UUID。
示例代碼如下:
package mainimport ("fmt""github.com/google/uuid"
)func main() {// 生成一個新的 UUIDnewUUID := uuid.New()fmt.Printf("Generated UUID: %s\n", newUUID)// 獲取并打印UUID的變體variant := newUUID.Variant()fmt.Printf("UUID Variant: %d\n", variant)// 獲取并打印UUID的版本version := newUUID.Version().String()fmt.Println(version)
}