2013年7月6日土曜日

UUID の Version の見分け方

UUID には いくつかのバージョンがあり、生成方法が定められている。
現在定義されているバージョンは以下の5つ。

Version生成方法
1 MAC-Address と 生成時刻によるもの
2 DCE Security version
3 名前(byte列)のMD5 ハッシュによるもの
4 ランダム
5 名前(byte列)の SHA-1 ハッシュによるもの


UUID の形式は以下のようになっている。

xxxxxxxx-xxxx-Vxxx-xxxx-xxxxxxxxxxxx

赤字の「V」のところがバージョン番号。


バージョン4


Java の標準ライブラリで生成できるのは、Version 4 と Version 3 の2つ。
まずは、Version 4。
UUID.randomUUID() で生成する。

for (int i = 0; i<10; i++) {
    UUID uuid = UUID.randomUUID();
    System.out.println(uuid);
}

b048c6b3-b36f-4c8d-97ea-96828a50a44c
84e291f7-4b37-4767-97c2-b0fea0fc5936
94cc812c-727f-49b0-85dd-e65a9afdeb65
99d57582-dd58-46cc-81e9-1449f2bfd761
ccd8505e-3fff-4a50-b671-d9adce7e896c
e6bf67b4-5f5a-4d37-aa26-f69aa670d747
a87db9b3-cd3c-4a80-a224-a809bf51905b
9639dca5-9bb0-4507-9baa-6bb07ba674e8
e95f8e5e-585d-4cd0-8751-beb0e183d3d2
0e99f22c-5608-4db9-a2b8-2c81c284b164

バージョン番号の部分だけ常に4になっている。


バージョン3


次に、Version 3。
Version 3 は 生成元になる byte 列を与えて、
UUID.nameUUIDFromBytes(bytes) で生成する。

Random rnd = new Random(System.currentTimeMillis());
for (int i = 0; i<10; i++) {
    byte[] bytes = new byte[10];
    rnd.nextBytes(bytes);
    UUID uuid = UUID.nameUUIDFromBytes(bytes);
    System.out.println(uuid);
}

736dd106-0e66-3210-bc16-62fb09bb8240
40f13c0b-c669-36b8-adb1-f545254d84f5
521ce8b4-731c-3fb0-adf7-3c224ae30883
81c30ad9-aac4-3aed-9865-2160f6913f8e
01da84aa-9805-352d-ab17-8c36620f9a4b
8bb1af96-e9d7-3770-8f77-9ec7a7f1e87a
de5b8017-f80e-3433-b7c8-5a8fed4afe22
9538654f-cd0b-3527-9d99-f4197a071afc
e7a00f80-0e01-316b-bcf2-b0f3764a576d
17276e00-279b-3049-b19f-205568a3cb72

バージョン番号の部分だけ常に3になっている。


バージョン1


Version 1 の UUID は、Java の標準ライブラリでは生成できない。
http://johannburkard.de/software/uuid/ の UUID Generator を使ってみる。

for (int i = 0; i<10; i++) {
    com.eaio.uuid.UUID uuid = new com.eaio.uuid.UUID();
    System.out.println(uuid);
}

cb251350-e0a0-11e2-99aa-XXXXXXXXXXXX
cb251351-e0a0-11e2-99aa-XXXXXXXXXXXX
cb251352-e0a0-11e2-99aa-XXXXXXXXXXXX
cb251353-e0a0-11e2-99aa-XXXXXXXXXXXX
cb251354-e0a0-11e2-99aa-XXXXXXXXXXXX
cb251355-e0a0-11e2-99aa-XXXXXXXXXXXX
cb251356-e0a0-11e2-99aa-XXXXXXXXXXXX
cb251357-e0a0-11e2-99aa-XXXXXXXXXXXX
cb251358-e0a0-11e2-99aa-XXXXXXXXXXXX
cb251359-e0a0-11e2-99aa-XXXXXXXXXXXX

バージョン1のUUIDが生成できた。
XXXXX の部分は 実際は、MACアドレスが入っている。

生成間隔を少し空けてみる。

for (int i = 0; i<10; i++) {
    com.eaio.uuid.UUID uuid = new com.eaio.uuid.UUID();
    System.out.println(uuid);
    Thread.sleep(100);
}

15641320-e0a2-11e2-a4a2-XXXXXXXXXXXX
15735560-e0a2-11e2-a4a2-XXXXXXXXXXXX
158297a0-e0a2-11e2-a4a2-XXXXXXXXXXXX
1591d9e0-e0a2-11e2-a4a2-XXXXXXXXXXXX
15a11c20-e0a2-11e2-a4a2-XXXXXXXXXXXX
15b05e60-e0a2-11e2-a4a2-XXXXXXXXXXXX
15bfa0a0-e0a2-11e2-a4a2-XXXXXXXXXXXX
15cee2e0-e0a2-11e2-a4a2-XXXXXXXXXXXX
15de2520-e0a2-11e2-a4a2-XXXXXXXXXXXX
15ed6760-e0a2-11e2-a4a2-XXXXXXXXXXXX

生成間隔をあけると生成時刻のフィールドの間隔も変わる。
先ほどは time-low 部の末尾が0からインクリメントされていたが、 今回は常に0になっている。
同一ID生成を防ぐために予備フィールドを持っていて、 前回生成時のIDを覚えておき、 同じ時刻に生成された場合にはインクリメントするようになっているのだろう。

0 件のコメント:

コメントを投稿