Java에서 가장 중요한 UUID 비트를 사용하는 충돌 가능성


235

내가 사용 Long uuid = UUID.randomUUID().getMostSignificantBits()하면 충돌이 발생할 가능성이 큽니다. 최하위 비트를 차단하므로 충돌이 발생할 가능성이 있습니까?

답변:


213

documentation 에 따르면 정적 메소드 UUID.randomUUID()는 유형 4 UUID를 생성합니다.

즉, 일부 유형 정보에는 6 비트가 사용되고 나머지 122 비트는 임의로 할당됩니다.

6 개의 비 랜덤 비트는 UUID의 최상위 절반에 4 개, 최하위 절반에 2 개가 분배됩니다. 따라서 UUID의 최상위 절반에는 60 비트의 임의성이 포함되므로 충돌을 발생시키기 위해 평균적으로 2 ^ 30 UUID를 생성해야합니다 (전체 UUID의 경우 2 ^ 61과 비교).

그래서 나는 당신이 오히려 안전하다고 말할 것입니다. 그러나 Carl Seleborg가 언급했듯이 다른 유형의 UUID에는 이것이 사실이 아닙니다.

또한 UUID의 최소 절반을 사용하거나 SecureRandom을 사용하여 임의의 긴 길이를 생성하면 약간 나아질 것입니다.


3
이것이 완전히 정확하지는 않습니다. 구현을 보면 버전 / 변형 정보가 가장 중요한 비트가 아니라 중간에 저장되어 있음이 분명합니다.
Tom

2
@RasmusFaber Tom 의 의견 은 정확합니다. 여기에서 정답 은 유형 정보 인 6 개의 최상위 비트 에 대한 정보입니다. 실제로 6 비트의 비 랜덤 데이터가 있지만 4 비트는 버전 4를 식별하고 2 개의 다른 비트는 예약되어 있습니다. 4 비트와 2 비트는 128 비트 값의 중간 부근에서 다른 위치에 있습니다. 참고 항목 위키 백과 문서를 .
Basil Bourque



10

임의의 긴 값을 생성하는 것이 좋으며 모든 비트는 임의입니다. Java 6에서 new Random ()은 System.nanoTime ()과 카운터를 시드로 사용합니다.

다른 수준의 고유성이 있습니다.

여러 시스템에서 고유성이 필요한 경우 고유 ID 또는 고유 ID 배치를 할당하기위한 중앙 데이터베이스 테이블이있을 수 있습니다.

하나의 앱에서 고유성을 필요로하는 경우 카운터 (또는 요구 사항에 따라 currentTimeMillis () * 1000 또는 nanoTime ()에서 시작하는 카운터) 만 있으면됩니다.


7

YYYYDDDD접두사로 시간 (년 + 년)을 사용하십시오. 이는 테이블 및 인덱스에서 데이터베이스 조각화를 줄입니다. 이 메소드는를 반환합니다 byte[40]. Active Directory SID ( varbinary(85))가 LDAP 사용자의 핵심이고 응용 프로그램 자동 생성 ID가 비 LDAP 사용자에 사용되는 하이브리드 환경에서이 도구를 사용했습니다. 또한 거래 테이블 (뱅킹 산업)에서 매일 많은 수의 트랜잭션 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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.