230


44

JavaでUUIDの最上位ビットを使用した衝突の可能性

Long uuid = UUID.randomUUID()。getMostSignificantBits()を使用している場合は、衝突が発生する可能性が高くなります。 最下位ビットが切り捨てられるので、衝突に遭遇する可能性がありますね。

5 Answer


211


http://docs.oracle.com/javase/7/docs/api/java/util/UUID.html [the documentation]によると、静的メソッド `UUID.randomUUID()`はタイプ4のUUIDを生成します。

これは、6ビットが何らかのタイプ情報に使用され、残りの122ビットがランダムに割り当てられることを意味します。

6個の非ランダムビットは、UUIDの最上位半分に4個、最下位半分に2個で分配されます。 そのため、UUIDの最上位半分には60ビットのランダム性が含まれています。つまり、衝突を起こすには平均2 ^ 30のUUIDを生成する必要があります(フルUUIDの2 ^ 61に対して)。

だから私はあなたがやや安全だと言うでしょう。 ただし、Carl Seleborgが述べているように、これは他のタイプのUUIDには絶対に当てはまりません。

ちなみに、UUIDの最下位の半分を使用する(またはSecureRandomを使用してランダムなlongを生成する)ことで、少し良くなるでしょう。


55


Raymond Chenは、これに関して非常に優れたブログ記事を投稿しています。

http://blogs.msdn.com/oldnewthing/archive/2008/06/27/8659071.aspx[GUIDはグローバルに一意ですが、GUIDの部分文字列は一意ではありません]


13


これはrandomUUIDを使用するための最良の例だと思います。


10


ランダムなlong値を生成するだけで、すべてのビットがランダムになります。 Java 6では、new Random()はSystem.nanoTime()とカウンタをシードとして使用します。

異なるレベルの一意性があります。

多数のマシンで一意性が必要な場合は、一意のID、または一意のIDのバッチを割り当てるための中央データベーステーブルがあります。

1つのアプリに独自性を持たせる必要がある場合は、カウンター(または要件に応じてcurrentTimeMillis()* 1000またはnanoTime()から始まるカウンター)だけを使用できます。


7


接頭辞としてTime YYYYDDDD(Year Day of Year)を使います。 これにより、テーブルとインデックスのデータベースの断片化が減少します。 このメソッドは byte [40]`を返します。 私はActive DirectoryのSID( `varbinary(85))がLDAPユーザーのためのキーであり、アプリケーションの自動生成されたIDが非LDAPユーザーのために使われるハイブリッド環境でそれを使いました。 また、トランザクションテーブル(銀行業界)における1日あたりの大量のトランザクションは、キーに標準の `Int`型を使用することはできません。

private static final DecimalFormat timeFormat4 = new DecimalFormat("0000;0000");

public static byte[] getSidWithCalendar() {
    Calendar cal = Calendar.getInstance();
    String val = String.valueOf(cal.get(Calendar.YEAR));
    val += timeFormat4.format(cal.get(Calendar.DAY_OF_YEAR));
    val += UUID.randomUUID().toString().replaceAll("-", "");
    return val.getBytes();
}