ゆるテックノート

UUIDとは?

UUID(Universally Unique Identifier)は、128ビット(16バイト)の識別子で、発行元が分散していても重複しにくいよう設計されています。ハイフン区切りの16進数で表現され、DB・メッセージング・URLなど幅広く使われます。

🪪 UUIDの概要

「ほぼ衝突しないIDを好きな場所で発行できる」のがUUIDの強みです。

押さえておきたい特徴

  • 128ビット長で、表記は 8-4-4-4-12 の16進数(計36文字、ハイフン含む)
  • 発行に中央サーバーを必要とせず、並列生成しても重複しにくい
  • 一意性は確率的保証であり、ゼロ衝突を「数学的に」保証するものではない

表記例

123e4567-e89b-12d3-a456-426614174000

🧩 構造とビット配置

ハイフンで5ブロックに分かれますが、実態は128ビットの連続データです。

ブロックごとの役割(一般形)

部分 bit長 概要
time_low / rand 32 先頭の32ビット。バージョンに応じて時刻や乱数が入る。
time_mid / rand 16 第2ブロック。
version + bits 16 先頭4ビットでバージョンを表す(1,4,5,7など)。
variant + bits 16 先頭数ビットで「RFC 4122 系列か」を示す。
node / rand 48 末尾の48ビット。MAC相当、もしくは乱数が入る。

バージョンビットとバリアント

  • 🔍 3桁目のハイフン直後の先頭16進1桁が「バージョン」を表す(例: xxxxxxxx-xxxx-4xxx-xxxx-xxxxxxxxxxxx は v4)。
  • 🔍 4桁目ブロック先頭の2~3ビットが「バリアント」を表し、一般的なRFC 4122形式では `8,9,a,b` のいずれかになる。

🧭 主なバージョンと違い

用途により「予測しづらさ」「時系列ソートのしやすさ」が異なります。

代表バージョン一覧

バージョン 生成方法 適した用途
v1 時刻+MACアドレスベース 順序性が欲しいがMAC露出を避けたい場合は非推奨。プライバシーと再現性に注意。
v4 暗号学的擬似乱数 もっとも一般的。とにかく予測されにくいIDが欲しい場合。
v5 名前空間付きハッシュ(SHA-1) 入力値から再現可能な決定的IDが必要な場合(例: URL→UUID)。
v7 時刻+ランダム(ミリ秒ベース) 最近の推奨。ソートしやすく、v1より秘匿性が高い。DBインデックスにも向く。

選び方の目安

  • 🧠 順序性が欲しく、挿入順に近い並びでソートしたい→ v7(または ULID 相当)
  • 🧠 衝突確率を下げたい・推測されにくいIDが欲しい→ v4
  • 🧠 同じ入力から同じIDを再生成したい→ v5(名前空間+入力の組み合わせで決定)

⚙️ 生成時の注意点

「乱数の質」と「時刻の扱い」が安全性・運用性を左右します。

安全に生成するためのチェック

  • ✔️ v4は暗号学的安全な乱数(/dev/urandom, crypto/rand など)で生成するライブラリを使う
  • ✔️ v1でMACアドレスを含めたくない場合は「ランダムノード」対応の実装を選ぶ
  • ✔️ 時計が巻き戻る可能性がある環境では、時刻ベースのバージョンの単調性が崩れる点に注意

衝突リスクの直感

v4の衝突確率は 2^122 分の1(バリアント・バージョンを除く)。数十億単位でも現実的にはほぼ衝突しませんが、事業規模や規制に応じて「絶対に重複させない」仕組み(DBユニーク制約等)を併用すると安心です。

🧰 よくある用途

利用例

  • 📌 マイクロサービス間で被りにくいリソースID(注文ID、トレースIDなど)
  • 📌 クライアントサイドで発行してもDBの主キーに使える識別子
  • 📌 ログの相関ID、メッセージキューのメッセージID、URLの一意キー

🛠️ 保管・運用のベストプラクティス

フォーマット揺れやインデックス断片化を避けると、運用が安定します。

実務でのポイント

  • 🔧 DBで高速に扱いたい場合は、v7など時間順になる形式を選びクラスタードインデックスの断片化を抑える
  • 🔧 文字列長を揃えるため、小文字ハイフン区切りに統一するか、BINARY(16) で生バイト保存する
  • 🔧 URLに埋め込む場合、ハイフンを含む標準形で十分。短縮したい場合は Base32/Base64url 等へエンコードする
  • 🔧 入力バリデーションでは「バージョン」もチェックすると想定外フォーマットの混入を防げる