web-dev-qa-db-ja.com

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

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

231
dlinsin

ドキュメント によると、静的メソッドUUID.randomUUID()はタイプ4 UUIDを生成します。

つまり、一部のタイプ情報には6ビットが使用され、残りの122ビットはランダムに割り当てられます。

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

ですから、あなたはかなり安全だと思います。ただし、Carl Seleborgが述べているように、これは他のタイプのUUIDには絶対に当てはまらないことに注意してください。

ちなみに、UUIDの最下位の半分を使用する(またはSecureRandomを使用してランダムなlongを生成する)ことで、わずかに改善されます。

211
Rasmus Faber

レイモンド・チェンは、これに関する本当に素晴らしいブログ投稿をしています:

GUIDはグローバルに一意ですが、GUIDのサブストリングはそうではありません

55
Carl Seleborg

これがrandomUUIDを使用する最良の例だと思います:

http://www.javapractices.com/topic/TopicAction.do?Id=56

13
Kannika

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

一意性にはさまざまなレベルがあります。

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

1つのアプリで一意性が必要な場合は、カウンター(または要件に応じてcurrentTimeMillis()* 1000またはnanoTime()から開始するカウンター)のみを使用できます。

10
Peter Lawrey

プレフィックスとしてTime YYYYDDDD(年+年の日)を使用します。これにより、テーブルとインデックスのデータベースの断片化が減少します。このメソッドは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();
}
7
Dr Bob