파이썬에서 uuid.uuid1 () 대 uuid.uuid4 ()를 언제 사용해야합니까?


207

문서와 의 차이점을 이해합니다 .

uuid1():
호스트 ID, 시퀀스 번호 및 현재 시간에서 UUID 생성

uuid4():
임의의 UUID를 생성합니다.

따라서 uuid1기계 / 시퀀스 / 시간 정보를 사용하여 UUID를 생성합니다. 각각을 사용하는 장단점은 무엇입니까?

uuid1()기계 정보를 기반으로하므로 개인 정보 보호 문제 가 발생할 수 있음을 알고 있습니다. 하나를 선택할 때 더 미묘한 지 궁금합니다. 나는 uuid4()완전히 임의의 UUID이기 때문에 지금 당장 사용 합니다. 그러나 uuid1충돌의 위험을 줄이기 위해 사용해야하는지 궁금합니다 .

기본적으로, 나는 하나를 사용하는 것에 대한 모범 사례에 대한 사람들의 팁을 찾고 있습니다. 감사!


3
다음은 UUID에 대한 대안입니다. 충돌 가능성은 무한하지만 UUID는 고유성을 보장하지 않습니다. 고유성을 보장하기 위해 복합 키를 [<system id>, <local id>]로 사용할 수 있습니다. 데이터 공유에 참여하는 각 시스템에는 시스템 설정 중 할당되거나 공통 ID 풀에서 확보 한 고유 한 시스템 ID가 있어야합니다. 로컬 ID는 특정 시스템 내에서 고유 한 ID입니다. 이것은 더 번거롭지 만 독창성을 보장합니다. 도와 주려고 노력하는 외주로 죄송합니다.
oᴉɹǝɥɔ

3
그가 언급 한 "개인 정보 보호 문제"를 처리하지 않습니다
Shrey

답변:


253

uuid1()충돌이 발생하지 않도록 보장합니다 (동시에 너무 많은 충돌을 생성하지 않는다는 가정하에). uuidmac 주소가 컴퓨터 전체에서 고유하게 사용되기 때문에 컴퓨터와 컴퓨터 사이에 연결이없는 것이 중요하다면 사용하지 않을 것 입니다.

100ns 미만에서 2 14 uuid1 이상을 생성하여 복제본을 생성 할 수 있지만 대부분의 사용 사례에서는 문제가되지 않습니다.

uuid4()말했듯이 임의의 UUID를 생성합니다. 충돌의 가능성은 정말로, 정말로, 정말로 작습니다. 충분히 작아서 걱정하지 않아도됩니다. 문제는 난수 생성기가 잘못되면 충돌 가능성이 높아진다는 것입니다.

Bob Aman의 훌륭한 답변은 그것을 훌륭하게 요약합니다. (전체 답변을 읽는 것이 좋습니다.)

솔직히 악의적 인 행위자가없는 단일 응용 프로그램 공간에서 초당 4 UUID를 생성하더라도 버전 4 UUID에서도 충돌이 발생하기 훨씬 전에 지구상의 모든 생명이 멸종됩니다.


죄송합니다. 완전히 조사하지 않고 댓글을 달았습니다. 버전 4 uuid가 버전 1 uuid와 충돌하지 않도록 예약 된 비트가 있습니다. 원래 의견을 삭제하겠습니다. 참조 tools.ietf.org/html/rfc4122
마크 랜섬에게

1
@gs 그래, 내가 읽고있는 내용이 이해가된다. uuid1은 "고유 한"반면, uuid4는 더 익명입니다. 따라서 이유가없는 한 기본적으로 uuid1을 사용하십시오. @ mark ransom : uuid1 / uuid4를 검색 할 때 멋진 답변이 나오지 않았습니다. 말의 입에서 곧바로 보인다.
rocketmonkeys

6
uuid1동일한 노드에서 초당 여러 개를 생성하는 경우 반드시 고유 한 UUID를 생성 할 필요는 없습니다. 예 : [uuid.uuid1() for i in range(2)]. 물론 내가 놓친 이상한 일이 일어나지 않는 한.
Michael Mior

1
@Michael : uuid1시퀀스 번호 (예제에서 네 번째 요소)를 가지므로 카운터에서 모든 비트를 사용하지 않으면 충돌이 없습니다.
Georg Schölly

3
@Michael : 충돌이 발생했을 때의 상황을 조사하고 찾은 정보를 추가했습니다.
Georg Schölly

32

당신이 고려할 수 있습니다 하나 개의 인스턴스 uuid1()가 아닌이 uuid4()있다 UUID를 별도의 시스템에서 발생하는 경우 다수의 온라인 거래를 목적으로 크기 조정을위한 여러 시스템에서 프로세스를 때, 예를 들어,.

이러한 상황에서, 예를 들어 의사 난수 생성기가 초기화되는 방식의 잘못된 선택으로 인해 충돌이 발생할 위험이 있으며, 잠재적으로 더 많은 수의 UUID가 생성되면 중복 ID를 생성 할 가능성이 높아집니다.

이 경우의 또 다른 관심은 uuid1()각 GUID가 처음 생성 된 시스템이 암시 적으로 (UUID의 "노드"부분에) 기록된다는 것입니다. 이것과 시간 정보는 디버깅에만 도움이 될 수 있습니다.


20

우리 팀은 데이터베이스 업그레이드 스크립트를 위해 UUID1을 사용하는 데 어려움을 겪었습니다. 데이터베이스 업그레이드 스크립트는 몇 분 안에 ~ 120k UUID를 생성했습니다. UUID 충돌로 인해 기본 키 제약 조건이 위반되었습니다.

100 대의 서버를 업그레이드했지만 Amazon EC2 인스턴스에서이 문제가 몇 차례 발생했습니다. 시계 해상도가 좋지 않고 UUID4로 전환하면 문제가 해결 된 것 같습니다.


5

사용할 때주의 할 점은 uuid1당신이 (주지 않고 기본 호출을 사용하는 경우, clock_seq당신이 충돌로 실행의 기회가 매개 변수) : 당신은 임의성의 14 비트가을 (100ns의 내 18 개 항목을 생성하는 당신에게 충돌 참조의 약 1 %의 기회를 제공합니다 생일 역설 / 공격). 대부분의 사용 사례에서는이 문제가 발생하지 않지만 클럭 해상도가 낮은 가상 시스템에서는 문제가 발생할 수 있습니다.


7
@Guilaume 그것은 clock_seq....를 사용하여 좋은 연습의 예를 보는 것이 정말 도움이 될 것입니다 .
eric

@Guilaume이 확률 1 %를 어떻게 계산 했습니까? 14 비트의 임의성은 100ns 당> = 2 ^ 14 id를 생성 할 경우 충돌이 발생한다는 것을 의미하며 이는 100ns 당 대략 163 개의 id를 생성 할 때 충돌 가능성이 1 %임을 의미합니다.
Maks

1
@maks 내가 말했듯이, 당신은 생일 역설을 봐야합니다 .

3

아마도 언급되지 않은 것은 지방의 것입니다.

MAC 주소 또는 시간 기반 순서 (UUID1)는 무작위로 분산 된 것 (UUID4)보다 숫자를 더 가깝게 정렬하는 작업이 적기 때문에 데이터베이스 성능을 향상시킬 수 있습니다 ( 여기 참조 ).

두 번째 관련 문제는 원본 데이터가 손실되거나 명시 적으로 저장되지 않은 경우에도 UUID1을 사용하는 것이 디버깅에 유용 할 수 있다는 것입니다.


1

허용되는 답변 외에도 경우에 따라 유용 할 수있는 세 번째 옵션이 있습니다.

임의의 MAC이있는 v1 ( "v1mc")

임의의 브로드 캐스트 MAC 주소를 사용하여 의도적으로 v1 UUID를 생성하여 v1과 v4간에 하이브리드를 만들 수 있습니다 (v1 사양에서 허용됨). 결과 v1 UUID는 시간에 따라 다르지만 (일반 v1과 같지만) v4와 같은 모든 호스트 관련 정보가 없습니다. v1mc = 60 비트 시간 + 61 개의 랜덤 비트 = 121 개의 고유 비트; v4 = 122 개의 랜덤 비트.

처음에 이것이 Postgres의 uuid_generate_v1mc () 함수였습니다. 그 후 다음과 같은 파이썬을 사용했습니다.

from os import urandom
from uuid import uuid1
_int_from_bytes = int.from_bytes  # py3 only

def uuid1mc():
    # NOTE: The constant here is required by the UUIDv1 spec...
    return uuid1(_int_from_bytes(urandom(6), "big") | 0x010000000000)

(참고 : UUID 객체를 직접 만드는 더 길고 빠른 버전이 있습니다. 원하는 경우 게시 할 수 있습니다)


대량의 호출 / 초의 경우 시스템 임의성이 소진 될 가능성이 있습니다. 당신은 할 수 다음 stdlib 사용 random(아마도 빨라집니다) 대신 모듈. 그러나 경고 : 공격자가 RNG 상태를 파악하여 향후 UUID를 부분적으로 예측하려면 수백 개의 UUID 만 있으면됩니다.

import random
from uuid import uuid1

def uuid1mc_insecure():
    return uuid1(random.getrandbits(48) | 0x010000000000)

이 방법은 "같은"v4 (호스트에 구애받지 않음)이지만 더 나쁘다 (비트가 적고, urandom에 의존하는 등). uuid4와 비교했을 때 어떤 이점이 있습니까?
rocketmonkeys

이것은 v1이 시간 기반 품질에 유용하지만 더 강력한 충돌 저항과 호스트 개인 정보가 필요한 경우를위한 업그레이드 일뿐입니다. 한 가지 예는 데이터베이스의 기본 키입니다. v4와 비교할 때 v1 uuid는 디스크에 쓸 때 더 나은 지역성을 가지며 더 유용한 자연적인 정렬 등을 갖습니다. 그러나 공격자가 2 **를 예측하는 경우 61 비트는 보안 문제 (예 : uuid nonce)와 같은 $ diety입니다. 대신 uuid4를 사용하십시오 (나는 알고 있습니다!). Re : urandom을 사용하기 때문에 더 나쁘다. 파이썬에서 uuid4 ()도 urandom을 사용한다는 것이 무슨 뜻인지 잘 모르겠습니다.
Eli Collins

좋은 일입니다. 수행 할 수있는 작업 (코드)뿐만 아니라 원하는 이유도 확인하는 것이 좋습니다. 재 : urandom, 나는 당신이 무작위 배의 2 배를 소비한다는 것을 의미합니다 (uuid1의 경우 1, urandom의 경우 다른 것). 시스템 엔트로피를 더 빨리 사용할 수 있습니다.
rocketmonkeys

실제로 uuid4의 절반 정도입니다. uuid1 ()은 clock_seq에 14 비트를 사용하여 최대 2 바이트의 urandom으로 반올림합니다. uuid1mc 랩퍼는 48 비트를 사용하는데, 이는 6 바이트의 urandom에 맵핑되어야하며 호출 당 총 urandom (8)이 소비됩니다. uuid4는 모든 호출에 대해 urandom (16)을 직접 호출합니다.
엘리 콜린스
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.