UUID를 디자인의 일부로 사용해야 하는 경우는 언제입니까?

StackOverflow https://stackoverflow.com/questions/703035

  •  22-08-2019
  •  | 
  •  

문제

나는 정말로 요점을 보지 못한다. UUID.충돌 확률이 다음과 같다는 것을 알고 있습니다. 사실상 0, 하지만 사실상 0 불가능에 가깝지도 않습니다.

UUID를 사용할 수밖에 없는 예를 들어줄 수 있는 사람이 있나요?내가 본 모든 용도 중에서 UUID가 없는 대체 디자인을 볼 수 있습니다.물론 디자인이 약간 더 복잡할 수도 있지만 적어도 실패 확률이 0이 아닌 것은 아닙니다.

UUID는 나에게 전역 변수 냄새가 난다.전역 변수를 사용하여 더 단순한 디자인을 만드는 방법은 많지만 이는 단지 게으른 디자인일 뿐입니다.

도움이 되었습니까?

해결책

나는 Ruby용 UUID 생성기/파서를 작성했기 때문에 이 주제에 대해 상당히 잘 알고 있다고 생각합니다.네 가지 주요 UUID 버전이 있습니다.

버전 4 UUID는 본질적으로 암호학적으로 안전한 난수 생성기에서 가져온 16바이트의 무작위성이며, UUID 버전과 변형을 식별하기 위해 약간의 비트 조정이 포함됩니다.충돌할 가능성은 거의 없지만 PRNG를 사용하거나 정말, 정말, 정말, 정말, 정말 불운이 발생한 경우 발생할 수 있습니다.

버전 5 및 버전 3 UUID는 각각 SHA1 및 MD5 해시 함수를 사용하여 네임스페이스를 이미 고유한 데이터 조각과 결합하여 UUID를 생성합니다.예를 들어, 이를 통해 URL에서 UUID를 생성할 수 있습니다.여기서 충돌은 기본 해시 함수에도 충돌이 있는 경우에만 가능합니다.

버전 1 UUID가 가장 일반적입니다.그들은 네트워크 카드의 MAC 주소(스푸핑되지 않는 한 고유해야 함)와 타임스탬프, UUID를 생성하기 위한 일반적인 비트 조작을 사용합니다.MAC 주소가 없는 시스템의 경우 암호화된 보안 난수 생성기를 사용하여 6노드 바이트가 생성됩니다.타임스탬프가 이전 UUID와 일치할 정도로 두 개의 UUID가 순차적으로 빠르게 생성되면 타임스탬프가 1씩 증가합니다.다음 중 하나가 발생하지 않는 한 충돌이 발생해서는 안 됩니다.MAC 주소가 스푸핑되었습니다.두 개의 서로 다른 UUID 생성 애플리케이션을 실행하는 하나의 시스템은 정확히 동일한 순간에 UUID를 생성합니다.네트워크 카드가 없거나 MAC 주소에 대한 사용자 수준 액세스가 없는 두 시스템에는 동일한 무작위 노드 시퀀스가 ​​제공되며 정확히 동일한 순간에 UUID를 생성합니다.타임스탬프를 표시하고 0으로 롤오버하는 데 바이트가 부족합니다.

현실적으로 이러한 이벤트는 단일 애플리케이션의 ID 공간 내에서 우연히 발생하지 않습니다.예를 들어 인터넷 전체 규모에서 ID를 수락하거나 ID 충돌 시 악의적인 개인이 나쁜 짓을 할 수 있는 신뢰할 수 없는 환경이 아닌 이상 걱정할 필요가 없습니다.나와 동일한 버전 4 UUID를 생성하더라도 대부분의 경우에는 문제가 되지 않는다는 점을 이해하는 것이 중요합니다.저는 귀하와 전혀 다른 ID 공간에서 ID를 생성했습니다.내 응용 프로그램은 충돌에 대해 전혀 알지 못하므로 충돌은 중요하지 않습니다.솔직히, 악의적인 행위자가 없는 단일 응용 프로그램 공간에서는 버전 4 UUID에서도 초당 꽤 많은 UUID를 생성하더라도 충돌이 발생하기 훨씬 전에 지구상의 모든 생명체가 멸종될 것입니다.

또한 2^64 * 16은 256엑사바이트입니다.마찬가지로 단일 애플리케이션 공간에서 ID 충돌 가능성이 50%가 되려면 256엑사바이트 상당의 ID를 저장해야 합니다.

다른 팁

uuids가 당신에게 구매하는 것은 그렇지 않으면 매우 어려운 것은 고유 식별자를 얻는 것입니다. 중앙 당국과 상담하거나 조정할 필요없이. 일종의 관리 인프라없이 그러한 일을 얻을 수있는 일반적인 문제는 UUID가 해결하는 문제입니다.

생일 역설에 따르면 UUID 충돌이 발생할 가능성은 2^64 uuids가 생성되면 50%입니다. 이제 2^64는 꽤 큰 숫자이지만 충돌 가능성이 50%는 너무 위험 해 보입니다 (예 : 충돌 확률이 5%가되기 전에 얼마나 많은 UUID가 존재 해야하는지 - 확률이 너무 큰 것처럼 보입니다). .

해당 분석의 문제는 두 가지입니다.

  1. UUID는 완전히 무작위가 아닙니다. 시간 및/또는 위치 기반의 UUID의 주요 구성 요소가 있습니다. 따라서 충돌 할 수있는 진정한 기회를 얻으려면 충돌하는 UUID는 다른 UUID 생성기와 정확히 동시에 생성해야합니다. 나는 여러 uuid가 동시에 생성 될 수있는 합리적인 기회가 있지만,이 작은 uuid 세트 사이의 충돌 가능성을 거의 불가능하게 만들기에 충분한 다른 gunk (위치 정보 또는 임의 비트 포함)가 충분하다고 말하고 싶습니다. .

  2. 엄격히 말하면, UUID는 비교할 수있는 다른 UUID 세트 중에서만 독특해야합니다. 데이터베이스 키로 사용할 UUID를 생성하는 경우, 악의 대체 우주의 다른 곳에서 동일한 UUID가 COM 인터페이스를 식별하는 데 사용되는지는 중요하지 않습니다. Alpha-Centauri에 "Michael Burr"라는 다른 사람이 있다면 혼란을 일으키지 않을 것입니다.

모든 것이 0이 아닌 실패 가능성이 있습니다. 나는 uuids의 충돌보다 문제가 발생할 가능성이 훨씬 높다 (즉, 생각할 수있는 거의 모든 것).

"합리적으로"또는 "효과적으로" "효과적으로"에 중점을 둔다 : 현실 세계가 어떻게 작동하는지 충분히 좋다. "실질적으로 독특한"과 "진정한 독특한"사이의 격차를 다루는 데 관련된 계산 작업의 양은 엄청납니다. 독창성은 수익이 줄어든 곡선입니다. 그 곡선의 어느 시점에서, "고유 한"가 여전히 저렴한 곳 사이에는 선이 있으며, 우리는 매우 가파르게 구부러집니다. 더 많은 독창성을 추가하는 비용은 상당히 커집니다. 무한한 독창성은 무한한 비용이 있습니다.

uuid/guid는 비교적 말하면 계산적으로 빠르고 쉽고 쉬운 ID를 생성하는 방법입니다. 합리적으로 보편적으로 독특하다고 가정합니다. 이는 이전에 연결되지 않은 시스템의 데이터를 통합 해야하는 많은 시스템에서 매우 중요합니다. 예를 들어 : 두 개의 다른 플랫폼에서 실행되는 컨텐츠 관리 시스템이 있지만 어느 시점에서 한 시스템에서 컨텐츠를 다른 시스템으로 가져와야합니다. ID가 변경되기를 원하지 않으므로 시스템의 데이터 간의 참조는 그대로 유지되지만 시스템 B에서 생성 된 데이터와 충돌을 원하지 않습니다. UUID는이를 해결합니다.

UUID를 만드는 것이 반드시 필요한 것은 아닙니다.그러나 표준을 갖는 것이 편리합니다. 오프라인 사용자는 충돌 가능성이 매우 낮은 무언가에 대한 키를 생성할 수 있습니다.

이는 데이터베이스 복제 해결 등에 도움이 될 수 있습니다.

그것은 쉬울 것입니다 온라인 사용자는 오버헤드나 충돌 가능성 없이 무언가에 대한 고유 키를 생성할 수 있지만 UUID는 그런 용도가 아닙니다.

어쨌든 Wikipedia에서 가져온 충돌 확률에 대한 단어입니다.

이 숫자를 원근법으로 표현하기 위해, 운석에 부딪 칠 수있는 연간 위험은 170 억 개의 기회로 추정되며, 1 년에 수십억 개의 UUID를 만들고 하나의 복제를 할 확률과 동일합니다.다시 말해, 향후 100 년 동안 매 초마다 10 억 개의 UUID를 생성 한 후에 만 ​​하나의 복제본 만 생성 할 확률은 약 50%입니다.

또한 몸의 모든 입자가 당신이 앉아있는 의자를 통해 동시에 터널을 터널 할 확률이 0이되지 않으며 갑자기 바닥에 앉아있는 것을 발견 할 것입니다.

그것에 대해 걱정하십니까?

전형적인 예는 두 데이터베이스 사이를 복제 할 때입니다.

DB (a)는 int id 10과 함께 레코드를 삽입하고 동시에 DB (b)는 ID 10에서 AA 레코드를 만듭니다. 이것은 충돌입니다.

UUID를 사용하면 일치하지 않기 때문에 발생하지 않습니다. (거의 확실하게)

나는 uuids를 피할 계획이 있습니다. 어딘가에 서버를 설정하고 일부 소프트웨어가 보편적으로 고유 한 식별자를 원할 때마다 해당 서버에 연락하여 하나를 건네주십시오. 단순한!

우리가 완전히 악의를 무시하더라도 이것에 실질적인 문제가 있다는 것을 제외하고. 특히, 그 서버는 인터넷의 일부에서 실패하거나 도달 할 수 없게 될 수 있습니다. 서버 오류를 처리하려면 복제가 필요합니다. 매우 어렵다 올바르게 얻으려면 (합의 건물이 어색한 이유에 대한 Paxos 알고리즘에 관한 문헌을 참조하십시오) 꽤 느립니다. 또한 모든 서버가 'Net, 없음 해당 서브넷에 연결된 클라이언트는 모두 새 ID를 기다릴 것이기 때문에 무엇이든 할 수 있습니다.

따라서 ... 지구의 수명 동안 실패 할 가능성이없는 간단한 확률 적 알고리즘을 사용하여 배치 Pita가되어 빈번한 고장이있는 주요 인프라를 구축하십시오. 나는 내가 어느 쪽을 찾는 지 압니다.

간단한 데이터베이스 응용 프로그램을위한 대안을 살펴보면 새 개체를 만들기 전에 매번 데이터베이스를 쿼리 해야하는 경우 UUID를 사용하면 시스템의 복잡성으로 효과적으로 줄어들 수 있습니다. 부여 - int 키를 사용하는 경우 32 비트는 128 비트 UUID의 4 분의 1에 저장됩니다. 명백한 - UUID 생성 알고리즘은 단순히 숫자를 증가시키는 것보다 더 많은 계산 능력을 차지합니다. 그러나 - 누가 신경 쓰나요? 고유 한 숫자를 할당하기 위해 "권한"을 관리하는 오버 헤드는 의도 된 고유성 ID 공간에 따라 수분에 따라 쉽게 능가합니다.

uuid == 게으른 디자인에

나는 당신의 싸움을 선택하는 것에 대해 동의하지 않습니다. 중복 UUID가 통계적으로 불가능하고 수학이 입증 된 경우 왜 걱정해야합니까? 소규모 N UUID 생성 시스템 주위에 설계하는 데 시간을 소비하는 것은 비현실적이며 시스템을 개선 할 수있는 다른 방법은 항상 있습니다.

충돌 가능성에 대한 모든 이야기를 얻는 것은 아닙니다. 나는 충돌에 신경 쓰지 않는다. 그래도 성능에 관심이 있습니다.

https://dba.stackexchange.com/a/119129/33649

UUIDS는 매우 큰 테이블의 성능 재난입니다. (200k 행은 "매우 크지 않습니다.)

charcter 세트가 UTF8 일 때 #3은 정말 나쁩니다. char (36)는 108 바이트를 차지합니다!

UUIDS (GUIDS)는 매우 "무작위"입니다. 큰 테이블에서 고유하거나 기본 키로 사용하는 것은 매우 비효율적입니다. 새 UUID를 삽입하거나 UUID로 선택할 때마다 테이블/색인을 뛰어 넘어야하기 때문입니다. 테이블/인덱스가 캐시에 너무 커지면 (InnoDB_Buffer_Pool_Size 참조, RAM보다 작아야하는데, 일반적으로 70%) '다음'UUID는 캐시되지 않을 수 있으므로 느린 디스크 히트. 테이블/인덱스가 캐시보다 20 배 큰 경우, 1/20 (5%)의 적중 만 캐시됩니다. I/O 바운드입니다.

따라서 UUID를 사용하지 마십시오

"작은"테이블이 있거나 다른 장소에서 고유 한 ID를 생성하기 때문에 실제로 필요한 테이블이 필요합니다 (그리고 다른 방법을 알아 내지 못했습니다). UUID에 대한 자세한 내용 : http://mysql.rjweb.org/doc.php/uuid (표준 36-char uuids와 바이너리 (16) 사이를 변환하기위한 함수가 포함됩니다.)

같은 테이블에 고유 한 자동 _increment와 고유 한 UUID를 모두 갖는 것은 폐기물입니다.

인서트가 발생하면 모든 고유/기본 키를 중복을 확인해야합니다. 고유 한 키는 INGODB의 기본 키를 요구하는 데 충분합니다. 바이너리 (16) (16 바이트)는 다소 부피가 크지 만 (PK로 만드는 것에 대한 인수), 그렇게 나쁘지는 않습니다. 2 차 키가있을 때 부피가 중요합니다. Innodb는 각 보조 키의 끝에 PK를 조용히 해결합니다. 여기서 주요 교훈은 특히 매우 큰 테이블의 보조 키 수를 최소화하는 것입니다. 비교 : int signed는 040 억 범위의 4 바이트입니다. Bigint는 8 바이트입니다.

마지막 직장에서, 우리는 UUID로 독특하게 식별 된 제 3 자로부터 물건을 얻고있었습니다. 나는 UUID-> 긴 정수 조회 테이블을 넣고 긴 정수를 기본 키로 사용했습니다.

버전 1 알고리즘을 사용하여 동일한 MAC 주소에서 밀리 초당 10 개 미만의 UUID가 생성된다는 제약 조건에서 불가능한 충돌 인 것 같습니다.

개념적으로, UUID에 대한 원래 (버전 1) 생성 체계는 UUID 버전을 UUID를 생성하는 컴퓨터의 MAC 주소와 서부의 Gregorian Calendar를 채택한 이후 100 나노초 간격으로 연결하는 것이 었습니다. . 실제로 실제 알고리즘이 더 복잡합니다. 이 계획은 그것이 충분히 '불투명'이 아니라는 점에서 비판을 받았다. 그것은 UUID를 생성 한 컴퓨터의 정체성과 그 시간을 보여줍니다.

내가 어떻게 작동하는지 잘못 해석하면 누군가 나를 교정합니다

UUID가 나쁜 디자인이라고 말하는 사람들에게 ~할 수 있었다 (엄청나게 작은 확률로) 충돌하는 동안, DB가 생성 된 키가 충돌하지 않지만 ... 인간의 오류가 발생할 가능성은 DB 생성 키에서 충돌을 일으킬 가능성이 있다는 것을 알고 있습니다. UUID4 충돌. 우리 알다 DB가 재현되면 다시 1시에 ID를 시작하고 우리 중 얼마나 많은 사람들이 우리가 절대 필요하지 않을 것이라고 확신했을 때 테이블을 재현해야 했습니까? 나는 어떤 날에 알려지지 않은 unknowns와 함께 물건이 잘못되기 시작하면 돈을 uuid 안전에 넣었을 것입니다.

UUID를 요구하는 다른 사람의 API를 사용해야하는 경우를 제외하고는 항상 다른 해결책이 있습니다. 그러나 이러한 대안이 해결 될 것입니다 모두 uuids가하는 문제? 한 번에 모든 문제를 해결하기 위해 각각 다른 문제를 해결하기 위해 더 많은 해킹 계층을 추가하게 될 것입니까?

예, UUIDS가 충돌하는 것이 이론적으로 가능합니다. 다른 사람들이 지적했듯이, 그것은 단지 고려할 가치가 없을 정도로 우스운 일이 아닙니다. 그것은 결코 지금까지 일어난 적이 없으며 대부분은 결코 그렇게하지 않을 것입니다. 잊어 버려.

충돌을 피하는 가장 "명백한"방법은 단일 서버가 모든 삽입물에서 고유 ID를 생성하도록하는 것입니다. 이는 분명히 심각한 성능 문제를 일으키고 오프라인 생성 문제를 전혀 해결하지 못합니다. 죄송합니다.

다른 "명백한"솔루션은 고유 한 숫자의 블록을 미리 전달하는 중심 기관입니다. 이는 본질적으로 UUID V1이 생성기의 MAC 주소 (IEEE OUI를 통해)를 사용하여하는 일입니다. 그러나 모든 중앙 당국이 결국 나사를 조이기 때문에 MAC 주소가 중복되므로 실제로는 UUID V4 충돌보다 훨씬 가능성이 높습니다. 죄송합니다.

UUID를 사용하는 것에 대한 가장 좋은 주장은 그들이 "너무 큽니다"라는 것입니다. 그러나 (상당히) 작은 체계는 필연적으로 가장 흥미로운 문제를 해결하지 못할 것입니다. UUIDS의 크기는 이러한 문제를 해결하는 데 유용성의 고유 한 부작용입니다.

UUIDS가 제공하는 것을 필요로하는 문제가 충분하지 않으며,이 경우 다른 것을 자유롭게 사용할 수 있습니다. 그러나 문제가 예기치 않게 (그리고 대부분) 문제가 커지면 나중에 전환하고 처음에는 사용하지 않기 위해 스스로를 시작할 것입니다. 대신 성공을 위해 디자인하기 쉬운 경우 왜 실패를위한 디자인?

UUIDS는 전역 변수와 관련된 모든 나쁜 코딩 관행을 구현합니다. 다른 키트 조각에 분산 될 수있는 슈퍼 글로벌 변수이기 때문에 더 나쁩니다.

최근 프린터를 정확한 교체 모델로 교체하는 데 이러한 문제를 겪었으므로 클라이언트 소프트웨어 중 어느 것도 작동하지 않을 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top