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


235

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

回答:


213

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

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

6つの非ランダムビットは、UUIDの最上位半分に4つ、最下位半分に2つで配信されます。したがって、UUIDの最上位半分には60ビットのランダム性が含まれています。つまり、衝突を取得するには平均で2 ^ 30のUUIDを生成する必要があります(完全なUUIDの2 ^ 61と比較して)。

だからあなたはかなり安全だと思います。ただし、これは他のタイプのUUIDにはまったく当てはまらないことに注意してください。

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


3
これが完全に正しいかどうかはわかりません-実装を見ると、バージョン/バリアント情報が最上位ビットではなく、途中のどこかに格納されていることがわかります。
トム

2
@RasmusFaber トムのコメントは正しいです。ここでの答えはタイプ情報である最上位6ビットについて正しくありません。確かに6ビットの非ランダムデータがありますが、4ビットはバージョン4を識別し、他の2ビットは予約されています。4ビットと2ビットは、128ビット値の中央付近の異なる位置にあります。ウィキペディアの記事をご覧ください。
バジルブルク2015



10

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

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

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

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


7

時間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();
}

3
代わりに標準のV1 UUIDを使用しないのはなぜですか?
ShadowChaser 14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.