UUID:當自動遞增不夠時
為什麼唯一識別碼在分散式系統中至關重要?對比 UUID 與自增 ID 的優劣,了解 v4 和 v7 版本的區別,學習在資料庫和 API 中正確使用 UUID。
你的資料庫使用自動遞增 ID。1, 2, 3, 4... 簡單。
然後你合併兩個資料庫。或在 URL 中暴露 ID。或者有人發現他們可以通過遞增 URL 中的 ID 來猜測其他使用者的資料。
順序 ID 有問題。UUID 解決其中一些。
什麼是 UUID?
通用唯一識別碼。一個 128 位元數字,通常顯示為帶有破折號的 32 個十六進位字符:
550e8400-e29b-41d4-a716-446655440000
UUID 生成背後的數學使碰撞在天文學上不太可能。你可以在不同的機器上、不同的時間生成 UUID,無需協調,它們不會碰撞。
為什麼不直接使用自動遞增?
安全性。 順序 ID 洩露資訊。如果你的使用者 ID 是 15847,攻擊者知道至少有 15846 個其他使用者。他們可以透過嘗試順序 ID 來列舉資源。
分散式系統。 生成 ID 的多個伺服器需要協調以避免重複。UUID 不需要協調。
合併資料。 合併具有順序 ID 的資料庫是一場噩夢。UUID 乾淨地合併。
離線創建。 行動應用程式可以使用 UUID 離線創建記錄。無需等待伺服器分配的 ID。
UUID 版本
不是所有 UUID 都以相同的方式創建。
版本 1: 基於時間戳和 MAC 地址。唯一,但揭示何時何地創建。
版本 4: 隨機。最常見。沒有資訊洩露。
版本 7: 基於時間戳但可排序。較新的資料庫從中受益。
對於大多數用途,版本 4(隨機)是正確的選擇。
權衡
UUID 不是免費的。
大小。 128 位元 vs 整數的 32 位元。更大的索引,更多的儲存。
可讀性。user/15 比 user/550e8400-e29b-41d4-a716-446655440000 更容易記住。
效能。 隨機 UUID 在某些資料庫中導致索引片段化。UUID v7 解決了這個問題。
除錯。 在日誌中搜尋 UUID 與簡單數字相比很繁瑣。
何時使用什麼
何時使用自動遞增:
- 僅內部,從不暴露給使用者
- 簡單應用程式,單一資料庫
- 人類可讀性很重要
何時使用 UUID:
- ID 出現在 URL 或 API 中
- 多個系統創建記錄
- 透過模糊性的安全性有幫助
- 合併資料是可能的
實用技巧
不要在 MySQL 中使用 UUID 作為主鍵。 改為將它們用作次要唯一列。MySQL 的聚集索引在隨機 UUID 下表現不佳。
考慮 UUID v7。 如果你的資料庫支援它,時間戳可排序的 UUID 給你兩全其美。
為 URL 移除破折號。550e8400e29b41d4a716446655440000 仍然是有效的 UUID,並且在 URL 中更短。
UUID 解決順序 ID 無法解決的真實問題。但它們並不總是正確的選擇。根據你的實際要求選擇,而不是因為 UUID 聽起來更專業。