언제 디자인의 일부로 UUID를 사용해야합니까?
UUID 의 요점을 실제로 보지 못합니다 . 충돌 가능성은 사실상 nil 이지만 사실상 nil 은 불가능에 가깝지 않습니다.
UUID를 사용하는 것 외에는 선택의 여지가없는 사람이 있습니까? 내가 본 모든 용도에서 UUID가없는 대체 디자인을 볼 수 있습니다. 디자인이 약간 더 복잡 할 수는 있지만 적어도 0이 아닌 실패 확률은 없습니다.
UUID는 전역 변수처럼 냄새가납니다. 전역 변수가 단순한 디자인을 위해 만드는 방법은 여러 가지가 있지만 게으른 디자인입니다.
Ruby 용 UUID 생성기 / 파서를 작성 했으므로이 주제에 대해 합리적으로 잘 알고 있다고 생각합니다. 4 가지 주요 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를 생성합니다.
실제로 단일 응용 프로그램의 ID 공간 내에서 우연히 이러한 이벤트가 발생하지 않습니다. 예를 들어 인터넷 규모 또는 악의적 인 개인이 ID 충돌시 나쁜 일을 할 수있는 신뢰할 수없는 환경에서 ID를 수락하지 않는 한 걱정할 필요는 없습니다. 내가하는 것과 동일한 버전 4 UUID를 생성하는 경우 대부분의 경우 중요하지 않다는 것을 이해하는 것이 중요합니다. 나는 당신과 완전히 다른 ID 공간에서 ID를 생성했습니다. 내 응용 프로그램은 충돌에 대해 알지 못하므로 충돌은 중요하지 않습니다. 솔직히 악의적 인 행위자가없는 단일 응용 프로그램 공간에서 충돌이 발생하기 훨씬 전에 버전 4 UUID에서도 지구상의 모든 삶의 멸종이 발생할 것입니다.
또한 2 ^ 64 * 16은 256 엑사 바이트입니다. 마찬가지로 단일 애플리케이션 공간에서 ID 충돌 가능성이 50 %가되기 전에 256 엑사 바이트에 해당하는 ID를 저장해야합니다.
UUID가 다른 방법으로 수행하기가 매우 어려운 것은 중앙 기관과 협의하거나 조정하지 않고도 고유 한 식별자를 얻는 것 입니다. 일종의 관리 인프라없이 그러한 것을 얻을 수있는 일반적인 문제는 UUID가 해결하는 문제입니다.
생일 역설에 따르면 U ^ D 충돌이 발생할 확률은 2 ^ 64 UUID가 생성되면 50 %라는 것을 읽었습니다. 2 ^ 64는 꽤 큰 숫자이지만 50 %의 충돌 확률은 너무 위험 해 보입니다 (예 : 5 %의 충돌 확률이 있기 전에 얼마나 많은 UUID가 존재해야합니까? .
이 분석의 문제점은 두 가지입니다.
UUID는 완전히 임의적이지는 않습니다. UUID의 주요 구성 요소는 시간 및 / 또는 위치 기반입니다. 따라서 충돌 가능성을 높이려면 충돌하는 UUID를 다른 UUID 생성기에서 정확히 동시에 생성해야합니다. 여러 UUID가 동시에 생성 될 수있는 합리적인 기회가 있지만, 매우 작은 UUID 세트 간의 충돌 가능성을 만들기에 충분한 다른 군크 (위치 정보 또는 임의의 비트 포함)가 충분하다고 말합니다. .
엄밀히 말하면 UUID는 다른 UUID와 비교할 때 고유해야합니다. 데이터베이스 키로 사용할 UUID를 생성하는 경우 악의적 인 대체 유니버스의 다른 곳에서 동일한 UUID를 사용하여 COM 인터페이스를 식별하는 것은 중요하지 않습니다. Alpha-Centauri에 "Michael Burr"라는 다른 사람이 있으면 혼동을 일으키지 않습니다.
모든 것이 실패 가능성이 0이 아닙니다. UUID의 충돌보다 훨씬 더 많은 문제가 발생할 가능성에 집중합니다.
"합리적으로"또는 "효과적으로"에 중점을 둡니다. 현실 세계가 작동하는 방식은 충분합니다. "실제적으로 독창적"과 "완전히 독창적"사이의 격차를 다루는 데 필요한 계산 작업의 양은 엄청납니다. 고유성은 수익이 감소하는 곡선입니다. 그 곡선의 어느 시점에서, "고유 한 (unique enough)"이 여전히 저렴한 곳에 선이 있으며, 우리는 매우 가파르게 구부립니다. 더 많은 고유성을 추가하는 비용이 상당히 커집니다. 무한한 독창성에는 무한한 비용이 있습니다.
UUID / GUID는 상대적으로 할 수있는 ID 생성하는 계산 빠르고 쉬운 방법 말하기입니다 합리적으로 보편적으로 고유 한 가정을. 이것은 이전에 연결되지 않은 시스템의 데이터를 통합해야하는 많은 시스템에서 매우 중요합니다. 예를 들어, 두 개의 다른 플랫폼에서 실행되는 컨텐츠 관리 시스템이 있지만 어느 시점에서 한 시스템에서 다른 시스템으로 컨텐츠를 가져와야하는 경우입니다. ID를 변경하지 않으려면 시스템 A의 데이터 간 참조는 그대로 유지하지만 시스템 B에서 작성된 데이터와 충돌하지는 않습니다. UUID가이를 해결합니다.
UUID를 생성 할 필요는 없습니다. 그러나 오프라인 사용자가 충돌 가능성이 매우 낮은 무언가에 대한 키를 생성 할 수 있는 표준을 갖는 것이 편리합니다 .
이것은 데이터베이스 복제 해결 등에 도움이 될 수 있습니다.
온라인 사용자는 오버 헤드 나 충돌 가능성없이 무언가에 대한 고유 키를 쉽게 생성 할 수 있지만 UUID가 아닙니다.
어쨌든 위키피디아에서 가져온 충돌 확률에 대한 단어 :
이러한 수치를 종합적으로 살펴보면 연간 운석에 타격을 입을 위험이 연간 170 억 건으로 1 년에 수십 조 조의 UUID를 생성하고 1 건의 복제본을 가질 확률에 해당하는 것으로 추정됩니다. 다시 말해, 향후 100 년 동안 초당 10 억 개의 UUID를 생성 한 후에 만 하나의 복제본을 생성 할 확률은 약 50 %입니다.
또한 신체의 모든 입자가 앉은 의자를 통해 동시에 터널을 뚫고 갑자기 바닥에 앉아있을 확률이 0이 아닙니다.
당신은 그것에 대해 걱정합니까?
전형적인 예는 두 데이터베이스간에 복제하는 경우입니다.
DB (A)는 int ID 10의 레코드를 삽입하는 동시에 DB (B)는 ID 10의 aa 레코드를 작성합니다. 이는 충돌입니다.
UUID를 사용하면 일치하지 않으므로 이런 일이 발생하지 않습니다. (거의 확실하다)
UUID를 피하기위한 계획이 있습니다. 서버를 어딘가에 설치하고 특정 소프트웨어가 보편적으로 고유 한 식별자를 원할 때마다 해당 서버에 접속하여 서버를 전달하도록하십시오. 단순한!
비록 우리가 명백한 악의를 무시하더라도 이것에 대한 실제적인 문제가 있다는 것을 제외하고는. 특히 해당 서버는 인터넷의 일부에서 장애가 발생하거나 연결할 수 없게됩니다. 서버 장애를 처리하려면 복제가 필요 하며 제대로 이해 하기 가 매우 어렵습니다 (합의 구축이 어색한 이유는 Paxos 알고리즘에 대한 문헌 참조). 모든 서버가 '인터넷의 특정 부분에서 도달 할 수없는 경우 또한, 어느 것도 해당 서브넷에 연결된 클라이언트는 모든 새로운 ID를 기다리고있을 것이기 때문에 아무것도 할 수 없습니다.
So... use a simple probabilistic algorithm to generate them that is unlikely to fail during the lifetime of the Earth, or (fund and) build a major infrastructure that is going to be a deployment PITA and have frequent failures. I know which one I'd go for.
If you just look at the alternatives e.g. for a simple database application, to have to query the database every time before you create a new object, you will soon find that using UUID can effectively reduce to complexity of your system. Granted - if you use int keys the are 32bit, which will store in a quarter of the 128bit UUID. Granted - UUID generation algorithms take up more computational power than simply incrementing a number. But - who cares? The overhead of managing an "authority" to assign otherwise unique numbers easily outweighs that by orders of magnitude, depending on your intended uniqueness ID space.
On UUID==lazy design
I disagree its about picking your fights. If a duplicate UUID is statistically impossible and the maths is proven then why worry? Spending time designing around your small N UUID generating system is impractical, there are always a dozen other ways you can improve your system.
i don't get all the talk about the likelihood of collision. I don't care about collision. I care about performance though.
https://dba.stackexchange.com/a/119129/33649
UUIDs are a performance disaster for very large tables. (200K rows is not "very large".)
Your #3 is really bad when the CHARCTER SET is utf8 -- CHAR(36) occupies 108 bytes!
UUIDs (GUIDs) are very "random". Using them as either a UNIQUE or a PRIMARY key on large tables is very inefficient. This is because of having to jump around the table/index each time you INSERT a new UUID or SELECT by UUID. When the table/index is too large to fit in cache (see innodb_buffer_pool_size, which must be smaller than RAM, typically 70%), the 'next' UUID may not be cached, hence a slow disk hit. When the table/index is 20 times as big as the cache, only 1/20th (5%) of hits are cached -- you are I/O-bound.
So, don't use UUIDs unless either
you have "small" tables, or you really need them because of generating unique ids from different places (and have not figured out another way to do it). More on UUIDs: http://mysql.rjweb.org/doc.php/uuid (It includes functions for converting between standard 36-char UUIDs and BINARY(16).)
Having both a UNIQUE AUTO_INCREMENT and a UNIQUE UUID in the same table is a waste.
When an INSERT occurs, all unique/primary keys must be checked for duplicates. Either unique key is sufficient for InnoDB's requirement of having a PRIMARY KEY. BINARY(16) (16 bytes) is somewhat bulky (an argument against making it the PK), but not that bad. The bulkiness matters when you have secondary keys. InnoDB silently tacks the PK onto the end of each secondary key. The main lesson here is to minimize the number of secondary keys, especially for very large tables. For comparision: INT UNSIGNED is 4 bytes with range of 0..4 billion. BIGINT is 8 bytes.
At my last job, we were getting objects from third parties that were uniquely identified with UUID. I put in a UUID->long integer lookup table and used long integer as my primary keys because it was way faster that way.
Using the version 1 algorithm it seems that it is impossible collision under the constraint that less than 10 UUIDs per millisecond are generated from the same MAC address
Conceptually, the original (version 1) generation scheme for UUIDs was to concatenate the UUID version with the MAC address of the computer that is generating the UUID, and with the number of 100-nanosecond intervals since the adoption of the Gregorian calendar in the West. In practice, the actual algorithm is more complicated. This scheme has been criticized in that it is not sufficiently 'opaque'; it reveals both the identity of the computer that generated the UUID and the time at which it did so.
Someone correct me if I misinterpreted how it works
To those saying that UUIDs are bad design because they could (at some ridiculously small probability) collide, while your DB generated keys won't... you know the chance of human error causing a collision on your DB generated keys because of some un-forseen need is FAR FAR FAR higher than the chance of UUID4 collision. We know that if the db is recreated it will start ids at 1 again, and how many of us have had to recreate a table when we were sure we would never ever need to? I'd put my money on UUID safeness when stuff starts going wrong with unknown-unknowns any day.
Aside from cases where you have to use someone else's API that demands a UUID, of course there's always another solution. But will those alternatives solve all the problems that UUIDs do? Will you end up adding more layers of hacks, each to solve a different problem, when you could have solved all of them at once?
Yes, it is theoretically possible for UUIDs to collide. As others have noted, it's ridiculously unlikely to the point that it's just not worth considering. It's never happened to date and most likely never will. Forget about it.
The most "obvious" way to avoid collisions is to let a single server generate unique IDs on every insert, which obviously creates serious performance problems and doesn't solve the offline generation problem at all. Oops.
The other "obvious" solution is a central authority that hands out blocks of unique numbers in advance, which is essentially what UUID V1 does by using the MAC address of the generating machine (via the IEEE OUI). But duplicate MAC addresses do happen because every central authority screws up eventually, so in practice this is far more likely than a UUID V4 collision. Oops.
The best argument against using UUIDs is that they're "too big", but a (significantly) smaller scheme will inevitably fail to solve the most interesting problems; UUIDs' size is an inherent side effect of their usefulness at solving those very problems.
It's possible your problem isn't big enough to need what UUIDs offer, and in that case, feel free to use something else. But if your problem grows unexpectedly (and most do), you'll end up switching later--and kick yourself for not using them in the first place. Why design for failure when it's just as easy to design for success instead?
UUIDs embody all of the bad coding practices associated with global variables, only worse, since they are superglobal variables which can be distributed over different pieces of kit.
Recently hit such an issue with the replacement of a printer with an exact replacement model, and found that none of the client software would work.
'Programing' 카테고리의 다른 글
MongoClient v3.0을 사용할 때 db.collection이 함수가 아닙니다 (0) | 2020.07.20 |
---|---|
"약식"또는 "정규식"의 올바른 속기는 무엇입니까? (0) | 2020.07.20 |
CouchDB 문서 모델링 원칙 (0) | 2020.07.20 |
캐시 무효화 — 일반적인 해결책이 있습니까? (0) | 2020.07.20 |
-std = c ++ 11과 -std = gnu ++ 11의 차이점은 무엇입니까? (0) | 2020.07.20 |