UUID Version 1 (タイムスタンプ + MACアドレス)
UUID v1の仕組みを解説。60ビットのタイムスタンプとMACアドレスを組み合わせた生成方法、プライバシーの問題点、そして新しいバージョンに置き換えられた理由を説明します。
詳細な説明
UUID Version 1はRFC 4122(2005年)で定義されたオリジナルのUUIDフォーマットの一つです。高精度のタイムスタンプと生成マシンのMACアドレスを組み合わせることで、時間と空間の両方にまたがる一意性を保証します。
ビットレイアウト(128ビット):
- ビット0-31:
time_low(タイムスタンプの下位32ビット) - ビット32-47:
time_mid(タイムスタンプの次の16ビット) - ビット48-51:バージョン
0001(1) - ビット52-63:
time_hi(タイムスタンプの上位12ビット) - ビット64-65:バリアント
10 - ビット66-79:クロックシーケンス(14ビット)
- ビット80-127:ノードID(48ビット、通常はMACアドレス)
タイムスタンプは1582年10月15日(グレゴリオ暦改革日)からの100ナノ秒間隔を表す60ビットの値です。これにより、v1 UUIDにはそのエポックから約3,600年分の一意なタイムスタンプが確保されています。
MACアドレスの問題: MACアドレスが含まれるため、UUID v1を見た人は生成マシンのネットワークインターフェース識別子を抽出できてしまいます。このプライバシー上の懸念が、ほとんどのユースケースでUUID v4が採用される要因となりました。代わりにランダムな48ビットのノードIDを使用することもできますが、空間的な一意性の保証が弱まります。
ソートに関する重要な注意点: タイムスタンプを含んでいるにもかかわらず、UUID v1は時刻順に辞書順ソートできません。タイムスタンプのビットが非連続のフィールドに分割されており(time_low が先頭に来ますが、これは下位ビットを保持しています)、文字列比較では時系列順にならないのです。UUID v6はこの問題を解決するために、v1のタイムスタンプビットをビッグエンディアン順に並び替えて作られました。
クロックシーケンス: 14ビットのクロックシーケンスフィールドは、システムクロックが巻き戻されたりノードIDが変更されたりした場合に対処します。通常はランダムに初期化され、クロックの逆行が検出されるとインクリメントされます。
Pythonでの生成:
import uuid
id = uuid.uuid1()
# Extract timestamp: id.time (100-ns intervals since 1582-10-15)
# Extract node: id.node (48-bit integer, usually MAC address)
現在の推奨事項: RFC 9562では新規アプリケーションにはv1よりもUUID v7を推奨しています。UUID v7はハードウェア識別子を漏洩させることなく時刻順序を提供し、よりシンプルで直感的なタイムスタンプレイアウトを採用しています。
ユースケース
UUID v1は、Apache Cassandra(TimeUUIDと呼ばれるバリアントを使用)や、時刻ベースの順序付けとハードウェアに紐づいた一意性に依存する古いエンタープライズJavaアプリケーションなど、レガシーシステムで依然として使われています。