Java의 UUID.randomUUID는 얼마나 좋습니까?


311

무작위 UUID 는 이론상 충돌 가능성이 매우 낮다는 것을 알고 있지만 실제로 randomUUID()충돌이 없다는 측면에서 Java가 얼마나 좋은지 궁금합니다 . 누구든지 공유 경험이 있습니까?


10
내 경험상, 나는 충돌을 본 적이 없다 ;-)
Thilo

4
알고리즘은 RFC1422에 지정되어 있습니다. ietf.org/rfc/rfc4122.txt
skaffman

8
@ skaffman : RFC는 임의의 숫자를 생성하는 데 사용되는 알고리즘에 대해 전혀 언급하지 않습니다.
Michael Borgwardt

4
이것은 더 개방적인 질문이므로 답을 정답으로 표시하지는 않습니다. 대신, 나는 내가 생각하는 각각의 답변에 대해 하나의 투표권을 줄 것이다 :)
Alvin

5
wikipedia에서 : ... 즉, 다음 100 년 동안 초당 10 억 UUID를 생성 한 후에 만 ​​하나의 복제본을 생성 할 확률은 약 50 %입니다.
MaVRoSCy

답변:


168

UUID는 java.security.SecureRandom"암호 적으로 강력"해야하는을 사용합니다. 실제 구현이 지정되어 있지 않고 JVM마다 다를 수 있지만 (구체적인 진술은 하나의 특정 JVM에만 유효 함을 의미) 출력은 통계적 난수 생성기 테스트를 통과해야합니다.

구현에 항상이 모든 것을 망치는 미묘한 버그가 포함될 수는 있지만 (OpenSSH 키 생성 버그 참조) Java UUID의 임의성에 대해 걱정할 구체적인 이유는 없다고 생각합니다.


34
"구현이 항상 미묘한 버그를 포함하는 것이 가능하다 ..." -또는 (주석 깡통 모자를 기르는) ... 의도적 인 미묘한 결함. <:-)
Stephen C

25
암호화 강도는 충돌 문제와 완전히 관련이 없습니다.
osa

14
@osa : 충돌을 일으키지 않는 것 (완벽한 임의성에서 예상되는 것 이상)은 RNG에 가장 낮은 품질 요구 사항이며 암호화 강도는 가장 높습니다. 즉, 강력한 암호 RNG는 것입니다 가장 확실히 예상보다 더 많은 충돌을 생성하지.
Michael Borgwardt

3
그러나 blogs.vmware.com/cto/… 내부에서 UUID를 생성 하는 JVM을 실행하면 충돌이 많이 발생할 수 있습니다. 모든 소프트웨어 RNG는 PRNG이며 궁극적으로 엔트로피 소스만큼 우수합니다. 동일하게 시드되는 두 PRNG도 동일하게 작동하며 일관되고 정확한 중복 서버 설정 및 시작 절차를 통해 놀라 울 정도로 자주 발생할 수 있습니다.
user508633

@ user508633 : 실제로는 특정한 경우에 100 % 충돌 속도를 기대하지만 실제로는 "일관되고 정확한 중복 서버 설정 및 시작 절차"를 넘어서는 매우 구체적인 경우입니다. VM을 복제하고 정상적으로 실행하는 경우 충돌 속도가 증가하지 않을 것이라고 확신합니다. SecureRandom의 자체 시드는 실제 엔트로피를 얻지 못하면 실행을 찾을 수없는 경우 실행을 차단합니다. seancassidy.me/wiggle-the-mouse-to-fix-the-test.html
Michael 보그 워드

114

Wikipedia는 http://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions에 대한 훌륭한 답변을 제공합니다 .

적어도 하나의 충돌의 50 % 확률을 갖기 위해 생성되어야하는 랜덤 버전 4 UUID의 수는 2.71 퀴 틸리 온이며, 다음과 같이 계산된다 :

...

이 숫자는 약 85 년 동안 초당 10 억 UUID를 생성하는 것과 같으며 UUID 당 16 바이트로이 많은 UUID를 포함하는 파일은 현재 존재하는 가장 큰 데이터베이스보다 몇 배 더 큰 약 45 엑사 바이트입니다. 수백 페타 바이트의 순서.

...

따라서 10 억 번의 중복 가능성이 발생하려면 103 조 버전 4 UUID를 생성해야합니다.


56
또한이 페이지에서 "지구상의 모든 사람이 6 억 UUID를 소유하고 있다면 한 번의 복제 확률은 약 50 %가 될 것입니다."
Jeff Axelrod

24
이것은 javas UUID와 같은 의사 난수 숫자가 아닌 진정한 임의성에만 해당됩니다.
Markus

9
@Markus : 완전히 틀 렸습니다. 우수한 의사 난수 RNG의 특히 암호화 적으로 강력한 RNG에 대한 충돌 가능성은 "진정한"임의성과 다릅니다.
Michael Borgwardt

6
@ 에릭-당신의 주장을 뒷받침 할 책임은 당신에게 있다고 생각합니다. FWIW, 유형 4 UUID가 더 자주 충돌하는 위치에 대해 생각할 수있는 유일한 시나리오는 다음과 같습니다 .1) 암호 난수의 잘못된 소스 또는 2) 손상된 UUID 라이브러리
Stephen C

13
이 질문에 대답하지 않습니다. 문제는 UUID.randomUUID()주어진 완벽한 난수 생성기의 이론적 기회가 아니라 Java의 무작위성에 관한 것입니다.
kratenko

69

누구든지 공유 경험이 있습니까?

2^122유형 4 UUID에 가능한 값 이 있습니다. (사양에 따르면 유형의 경우 2 비트, 버전 번호의 경우 4 비트가 손실됩니다.)

초당 1 백만 개의 임의 UUID를 생성한다고 가정하면 일생 동안 중복이 발생할 가능성은 거의 없습니다. 그리고 중복을 감지, 당신은에 대해 초당 1 백만 새 UUID를 비교하는 문제를 해결해야 할 것 이전에 생성 한 UUID가 모든 일을 !

실제 생활에서 복제본을 경험 한 사람 (즉, 실제로 눈에 띄는 ) 의 가능성은 실제로 작은 충돌보다 더 작습니다.

물론, 실제로는 난수 생성기가 아닌 의사 난수 생성기를 사용하게됩니다. 그러나 귀하가 암호화 강도 난수에 신용 제공 업체를 사용하는 경우 암호화 강도 될 것이며 반복 확률은 이상적인 (편향되지 않은) 난수 생성기와 동일 할 것이라고 확신 할 수 있습니다 .

그러나 "깨진"암호 난수 생성기와 함께 JVM을 사용하는 경우 모든 베팅이 해제됩니다. (그리고 여기에는 일부 시스템에서 "엔트로피 부족"문제에 대한 해결 방법이 포함되어있을 수도 있습니다. 또는 누군가가 시스템이나 업스트림에서 JRE에 영향을 줄 가능성이 있습니다.)


1-익명의 주석자가 제안한대로 "일종의 이진 btree"를 사용했다고 가정하면, 각 UUID에는 O(NlogN)비트의 N저밀도 및 랜덤 분포를 가정 하여 별개의 UUID 를 나타 내기 위해 약간의 RAM 메모리가 필요 합니다. 이제 1,000,000과 실험을 시작할 시간 (초)을 곱하십시오. 고품질 RNG의 충돌을 테스트하는 데 필요한 시간 동안 실용적이지 않다고 생각합니다. (가설적인) 영리한 표현조차도 아닙니다.


4
"(복제물을 감지하려면 이전에 생성 한 모든 UUID와 초당 백만 개의 새로운 UUID를 비교하는 문제를 해결해야합니다!)" 이진 트리 구조의 종류, 그것은 새로운 uuid 당 하나의 트리 하강 일 것입니다. 실제로 이전에 생성 된 모든 UUID와 개별적으로 비교할 필요는 없습니다.
user467257

20

나는 전문가는 아니지만 충분한 똑똑한 사람들이 수년 동안 Java의 난수 생성기를 보았을 것이라고 가정합니다. 따라서 임의의 UUID가 좋다고 가정합니다. 따라서 이론상 충돌 확률이 있어야합니다 ( 가능한 모든 UUID의 경우 약 1 : 3 × 10 ^ 38 입니다.이 방법이 임의의 UUID에서만 어떻게 변경되는지 아는 사람이 있습니까? 1/(16*4)위의 것입니까?)

실제 경험상 지금까지 어떤 충돌도 보지 못했습니다. 나는 내가 나의 첫번째 것을 얻는 날에 놀랍게도 긴 수염을 자랐을 것이다;)


10
wikipedia에서 : ... 즉, 다음 100 년 동안 초당 10 억 UUID를 생성 한 후에 만 ​​하나의 복제본을 생성 할 확률은 약 50 %입니다.
MaVRoSCy

1
실제로 wikipedia에 따르면 향후 85 년 동안의 말입니다 ... 나는 그것을 의지하지 않습니다. 누군가가 당신과 같은 UUID를 생성했습니다
smac89

12

전 고용주에서 우리는 임의의 UUID를 포함하는 고유 한 열을 가졌습니다. 배포 후 첫 주에 충돌이 발생했습니다. 물론, 확률은 낮지 만 제로가 아닙니다. 그래서 Log4j 2에 UuidUtil.getTimeBasedUuid가 포함되어 있습니다. 단일 서버에서 10,000 개 이상의 UUID / 밀리 초를 생성하지 않는 한 8,925 년 동안 고유 한 UUID를 생성합니다.


2
예. 그러나 문제는 임의의 UUID에 대해 묻는 것입니다.
Stephen C

1
충돌 가능성을 묻습니다. 그 의미는 그가 그들을 피하기를 원한다는 것입니다.
rgoers

1
(충돌은 PRNG의 파종에 대한 임의의 무작위 원인으로 인해 발생했을 가능성이 높습니다. 순수한 기회 때문일 수 있다고 생각합니다.)
Stephen C

9

UUID의 원래 생성 체계는 UUID를 생성하는 컴퓨터의 MAC 주소와 서부 그레고리력 채택 이후 100 나노초 간격으로 UUID 버전을 연결하는 것이 었습니다. 공간 (컴퓨터)과 시간 (간격 수)의 단일 지점을 나타내면 값 충돌 가능성이 거의 없습니다.


1
이 설명은 실제로 충돌을 보지 않도록 낙관적입니다. 이 문장에 대한 참조를 가리킬 수 있습니까 (일부 소스 코드가 더 좋을 것입니다)?
Dragan Marjanović '

ietf.org/rfc/rfc4122.txt 사양에서 이것을 발견했습니다 . 그럼에도 불구하고 구현을 보는 것이 좋습니다.
Dragan Marjanović '

1
그러나이 체계는 Java가 구현하는 것이 아닙니다. Java는 유형 4 UUID를 구현합니다. 이는 순수 임의이며 MAC 주소 또는 시간을 포함하지 않습니다. 또한 MAC 주소를 선택할 수있는 실제 및 가상 장치가 많이 있으므로 원래 알고리즘은 고유성을 보장하지 않습니다.
Søren Boisen 님이

8

많은 답변에서 충돌 가능성이 50 %에 도달하기 위해 얼마나 많은 UUID를 생성해야하는지에 대해 설명합니다. 그러나 50 %, 25 % 또는 1 %의 충돌 확률은 충돌이 (가상적으로) 불가능한 응용 프로그램에는 가치가 없습니다.

프로그래머는 일상적으로 발생할 수 있고 발생할 수있는 다른 이벤트를 "불가능한"것으로 기각합니까?

디스크 나 메모리에 데이터를 쓰고 다시 다시 읽을 때, 데이터가 정확하다는 것을 당연한 것으로 여깁니다. 우리는 손상을 감지하기 위해 장치의 오류 수정에 의존합니다. 그러나 감지되지 않은 오류의 가능성은 실제로 약 2-50 입니다.

임의의 UUID에 유사한 표준을 적용하는 것이 합리적이지 않습니까? 그렇게하면 약 1,000 억 개의 임의 UUID (2 36.5 ) 모음에서 "불가능한"충돌이 발생할 수 있습니다 .

이는 천문학적 수치이지만 국가 의료 시스템의 항목 별 청구 또는 많은 장치에서 고주파수 센서 데이터 로깅과 같은 애플리케이션은 이러한 한계에 부딪 칠 수 있습니다. Galaxy에 다음 Hitchhiker 's Guide를 작성하는 경우 각 기사에 UUID를 할당하지 마십시오!


비교하자면, Powerball 대성공에서 당첨 될 확률은 3 억분의 1이지만 1 천만에서 2 천만 티켓이 판매됩니다. 요점은 많은 사람들이 "불가능" 을 수억의 기회보다 적은 것으로 정의한다는 것입니다.
erickson 2016 년

4

대부분의 답변은 이론에 초점을 두었 기 때문에 제가 실제로 한 시험을 통해 토론에 무언가를 추가 할 수 있다고 생각합니다. 내 데이터베이스에는 Java 8 UUID.randomUUID ()를 사용하여 생성 된 약 450 만 개의 UUID가 있습니다. 다음은 내가 찾은 것입니다.

c0f55f62 -b990-47bc-8caa-f42313669948

c0f55f62 -e81e-4253-8299-00b4322829d5

c0f55f62 -4979-4e87-8cd9-1c556894e2bb


b9ea2498-fb32-40ef-91ef-0ba 00060fe64

be87a209-2114-45b3-9d5a-86d 00060fe64


4a8a74a6-e972-4069-b480-b dea1177b21f

12fb4958-bee2-4c89-8cf8-e dea1177b21f

실제로 무작위라면, 450 만 항목 만 고려하고 있기 때문에 이러한 종류의 유사한 UUID를 가질 확률은 상당히 낮습니다 (편집 참조). 이 기능이 없습니다 가진 충돌의 측면에서, 좋은 있지만, 그래서, 나를 위해, 그것은하지 않는 것 이 이론에있을 것 같은 좋은.

편집 :

많은 사람들이이 답변을 이해하지 못하는 것 같아서 요점을 명확히 할 것입니다. 유사성이 "작고"완전 충돌과는 거리가 멀다는 것을 알고 있습니다. 그러나 방금 Java의 UUID.randomUUID ()를 실제 난수 생성기와 비교하고 싶었습니다. 실제 질문입니다.

실제 난수 생성기에서 마지막 사례가 발생할 확률은 약 0.007 %입니다. 그러므로 나는 나의 결론이 옳다고 생각한다.

공식은이 위키 기사 en.wikipedia.org/wiki/Birthday_problem에서 설명됩니다.


6
사실이 아닙니다. 이러한 종류의 유사점은 4.5M UUID의 실제 난수 생성기에서도 발생할 수 있습니다. 당신이 준 UUID 사이의 유사점은 작고, 완전히 충돌하지는 않습니다.
user3711864

나는 유사성이 "작고"완전 충돌과는 거리가 멀다는 것에 완전히 동의합니다. 그러나 Java의 UUID.randomUUID ()를 실제 난수 생성기와 비교하려고했습니다 (질문입니다). 일부 계산을 통해 실제 난수 생성기에서 마지막 사례가 발생할 확률은 약 1-e ^ (-4500000 ^ 2 / (2 * 36 ^ 11)) = 0.007 % = 1입니다. 13k. 나는 매우 운이 좋을 것이다 :)
André Pinheiro

1
450 만 개의 아이템과 13k의 1 확률로, 부분 충돌이 346 번 예상되지 않습니까?
Ben Lee

@BenLee는 아니오, 우리는 450 만 항목을 고려할 때 그 사건이 일어날 확률을 계산했습니다. 각 항목에 대해 13k의 1 번의 기회는 아닙니다. 사용 수식 나는이 위키 문서에서 찾을 수 있습니다 en.wikipedia.org/wiki/Birthday_problem
안드레 핀 헤이에게

2
당신의 기대는 무엇입니까? 비슷하지 않습니까?
Koray Tugay

3

나는 작년에 복권에서 놀았는데 결코 이겼지 않았습니다 ....하지만 복권에 승자가있는 것 같습니다 ...

의사 : http://tools.ietf.org/html/rfc4122

유형 1 : 구현되지 않았습니다. UUID가 동시에 생성되면 충돌이 가능합니다. 이 문제를 우회하기 위해 impl을 인위적으로 a- 동기화 할 수 있습니다.

유형 2 : 구현을 보지 못했습니다.

유형 3 : md5 해시 : 충돌 가능 (128 비트 -2 기술 바이트)

유형 4 : 랜덤 : 충돌 가능 (복권으로). PRNG 알고리즘은 개발자가 선택하지 않으며 시스템이 "가난한"PRNG 알고리즘을 사용하도록 할 수 있기 때문에 jdk6 impl은 "true"보안 무작위를 사용하지 않습니다. 따라서 UUID는 예측 가능합니다.

유형 5 : sha1 해시 : 구현되지 않음 : 충돌 가능 (160 비트 -2 기술 바이트)


4
복권 당첨 확률은 10 또는 1 억 (10 ^ 7 또는 10 ^ 8) 또는 그와 비슷한 것입니다. 128 비트 난수와의 충돌 확률은 3.4 * 10 ^ 28입니다. 언제든지 추첨 티켓을주세요!
Stephen C

0

우리는 애플리케이션에서 Java의 임의 UUID를 1 년 이상 사용해 왔으며 그 기간은 매우 광범위했습니다. 그러나 우리는 결코 충돌을 겪지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.