Naprawdę nie widzę sensu UUID . Wiem, że prawdopodobieństwo kolizji jest praktycznie zerowe , ale w rzeczywistości zero nie jest nawet bliskie niemożliwości.
Czy ktoś może podać przykład, w którym nie masz innego wyjścia, jak tylko użyć UUID? Ze wszystkich zastosowań, które widziałem, widzę alternatywny projekt bez UUID. Oczywiście projekt może być nieco bardziej skomplikowany, ale przynajmniej nie ma niezerowego prawdopodobieństwa niepowodzenia.
UUID pachnie dla mnie jak zmienne globalne. Istnieje wiele sposobów, w jakie zmienne globalne ułatwiają projektowanie, ale jest to po prostu leniwy projekt.
architecture
uuid
Pirolistyczne
źródło
źródło
Odpowiedzi:
Napisałem generator / parser UUID dla Rubiego, więc uważam się za dość dobrze poinformowanego na ten temat. Istnieją cztery główne wersje UUID:
Identyfikatory UUID w wersji 4 to w zasadzie tylko 16 bajtów losowości pobieranych z kryptograficznie bezpiecznego generatora liczb losowych, z pewnymi zmianami bitów w celu zidentyfikowania wersji i wariantu UUID. Jest bardzo mało prawdopodobne, aby zderzyły się, ale może się zdarzyć, jeśli użyjesz PRNG lub jeśli po prostu masz naprawdę, naprawdę, naprawdę, naprawdę pecha.
Identyfikatory UUID wersji 5 i wersji 3 używają odpowiednio funkcji skrótu SHA1 i MD5 do łączenia przestrzeni nazw z fragmentem już unikalnych danych w celu wygenerowania identyfikatora UUID. Pozwoli to na przykład stworzyć UUID z adresu URL. Kolizje są tutaj możliwe tylko wtedy, gdy bazowa funkcja skrótu również ma kolizję.
Najpopularniejsze są identyfikatory UUID wersji 1. Używają adresu MAC karty sieciowej (który, o ile nie jest sfałszowany, powinien być unikalny), a także znacznika czasu i zwykłego manipulowania bitami w celu wygenerowania UUID. W przypadku maszyny, która nie ma adresu MAC, 6 bajtów węzłów jest generowanych za pomocą bezpiecznego kryptograficznie generatora liczb losowych. Jeśli dwa identyfikatory UUID są generowane sekwencyjnie na tyle szybko, że znacznik czasu pasuje do poprzedniego identyfikatora UUID, znacznik czasu jest zwiększany o 1. Kolizje nie powinny wystąpić, chyba że nastąpi jedno z poniższych: Adres MAC jest sfałszowany; Jedna maszyna z dwoma różnymi aplikacjami generującymi UUID generuje UUID dokładnie w tym samym momencie; Dwie maszyny bez karty sieciowej lub bez dostępu do adresu MAC na poziomie użytkownika otrzymują tę samą losową sekwencję węzłów i generują identyfikatory UUID dokładnie w tym samym momencie;
Realistycznie, żadne z tych zdarzeń nie występuje przypadkowo w przestrzeni identyfikatora pojedynczej aplikacji. O ile nie akceptujesz identyfikatorów w, powiedzmy, całym Internecie lub w niezaufanym środowisku, w którym złośliwe osoby mogą być w stanie zrobić coś złego w przypadku kolizji tożsamości, po prostu nie należy się tym martwić. Ważne jest, aby zrozumieć, że jeśli zdarzy ci się wygenerować ten sam identyfikator UUID w wersji 4 co ja, w większości przypadków nie ma to znaczenia. Wygenerowałem ID w zupełnie innej przestrzeni ID niż Twoja. Moja aplikacja nigdy nie dowie się o kolizji, więc kolizja nie ma znaczenia. Szczerze mówiąc, w pojedynczej przestrzeni aplikacji bez złośliwych aktorów wymieranie wszelkiego życia na Ziemi nastąpi na długo przed kolizją, nawet na UUID w wersji 4, nawet jeśli
Ponadto 2 ^ 64 * 16 to 256 eksabajtów. Tak jak w przypadku, należałoby przechowywać identyfikatory o wartości 256 eksabajtów, aby mieć 50% szans na kolizję identyfikatorów w pojedynczej przestrzeni aplikacji.
źródło
uuid.raw
poda ci ciąg bajtów. Tahash
metoda nie jest dla ciebie przydatna. Jest używany do tablic mieszających i operacji porównania wewnętrznie w Rubim. Wszystkie metody konwersji do iz różnych reprezentacji UUID są zdefiniowane jako metody klasowe i powinny być poprzedzone przedrostkiem"parse"
.To, co kupujesz za UUID, a jest bardzo trudne do zrobienia w inny sposób, to uzyskanie unikalnego identyfikatora bez konieczności konsultacji lub koordynacji z organem centralnym . Ogólnym problemem związanym z uzyskaniem czegoś takiego bez jakiejś zarządzanej infrastruktury jest problem rozwiązany przez UUID.
Czytałem, że zgodnie z paradoksem urodzinowym prawdopodobieństwo wystąpienia kolizji UUID wynosi 50% po wygenerowaniu 2 ^ 64 UUID. Teraz 2 ^ 64 to całkiem duża liczba, ale 50% szans na kolizję wydaje się zbyt ryzykowne (na przykład, ile UUID musi istnieć, zanim istnieje 5% szans na kolizję - nawet to wydaje się zbyt duże prawdopodobieństwo) .
Problem z tą analizą jest dwojaki:
Identyfikatory UUID nie są całkowicie losowe - istnieją główne składniki UUID oparte na czasie i / lub lokalizacji. Aby mieć realną szansę na kolizję, kolidujące UUID muszą być generowane dokładnie w tym samym czasie z różnych generatorów UUID. Powiedziałbym, że chociaż istnieje rozsądna szansa, że kilka UUID może zostać wygenerowanych w tym samym czasie, jest wystarczająco dużo innych gunk (w tym informacji o lokalizacji lub losowych bitów), aby prawdopodobieństwo kolizji między tym bardzo małym zestawem UUID było prawie niemożliwe .
Ściśle mówiąc, identyfikatory UUID muszą być unikalne w zestawie innych identyfikatorów UUID, z którymi można je porównywać. Jeśli generujesz UUID, który ma być używany jako klucz bazy danych, nie ma znaczenia, czy gdzieś indziej w złym alternatywnym wszechświecie ten sam UUID jest używany do identyfikacji interfejsu COM. Tak jak nie spowoduje to zamieszania, jeśli na Alpha-Centauri jest ktoś (lub coś) innego o imieniu „Michael Burr”.
źródło
Wszystko ma niezerową szansę niepowodzenia. Skoncentrowałbym się na znacznie bardziej prawdopodobnych problemach (tj. Prawie wszystkim, o czym możesz pomyśleć) niż kolizji UUID
źródło
Nacisk na „rozsądnie” lub, jak to ująłeś, „skutecznie”: wystarczająco dobre, jak działa prawdziwy świat. Ilość pracy obliczeniowej związanej z wypełnieniem luki między „praktycznie wyjątkowym” a „naprawdę wyjątkowym” jest ogromna. Wyjątkowość to krzywa z malejącymi zwrotami. W pewnym momencie na tej krzywej znajduje się granica między miejscem, w którym „wystarczająco wyjątkowy” jest nadal dostępny, a następnie BARDZO stromo zakręcamy. Koszt dodania większej wyjątkowości staje się dość duży. Nieskończona wyjątkowość ma nieskończony koszt.
UUID / GUID to, mówiąc relatywnie, obliczeniowo szybki i łatwy sposób generowania identyfikatora, który można rozsądnie założyć jako uniwersalny. Jest to bardzo ważne w wielu systemach, które wymagają integracji danych z wcześniej niepołączonych systemów. Na przykład: jeśli masz system zarządzania treścią, który działa na dwóch różnych platformach, ale w pewnym momencie musisz zaimportować zawartość z jednego systemu do drugiego. Nie chcesz, aby identyfikatory się zmieniały, więc odniesienia między danymi z systemu A pozostają nienaruszone, ale nie chcesz żadnych kolizji z danymi utworzonymi w systemie B. Rozwiązuje to UUID.
źródło
Tworzenie UUID nigdy nie jest absolutnie konieczne. Wygodne jest jednak posiadanie standardu, w którym każdy użytkownik offline może wygenerować klucz do czegoś z bardzo niskim prawdopodobieństwem kolizji.
Może to pomóc w rozwiązaniu replikacji bazy danych itp.
Użytkownikom online byłoby łatwo generować unikalne klucze do czegoś bez kosztów ogólnych lub możliwości kolizji, ale nie do tego służą identyfikatory UUID.
W każdym razie słowo na temat prawdopodobieństwa kolizji zaczerpnięte z Wikipedii:
źródło
Klasycznym przykładem jest replikacja między dwiema bazami danych.
DB (A) wstawia rekord o ID int 10 i jednocześnie DB (B) tworzy rekord o ID 10. To jest kolizja.
W przypadku UUID tak się nie stanie, ponieważ nie będą one pasować. (prawie na pewno)
źródło
Istnieje również niezerowe prawdopodobieństwo, że każda cząstka w twoim ciele jednocześnie przejdzie przez krzesło, na którym siedzisz, i nagle znajdziesz się na podłodze.
Martwisz się o to?
źródło
Mam schemat unikania identyfikatorów UUID. Skonfiguruj gdzieś serwer i miej go tak, że za każdym razem, gdy jakiś program potrzebuje uniwersalnego unikalnego identyfikatora, kontaktuje się z tym serwerem, a on go wydaje. Prosty!
Tyle że są z tym pewne praktyczne problemy, nawet jeśli ignorujemy jawną złośliwość. W szczególności ten serwer może ulec awarii lub stać się niedostępny z części Internetu. Radzenie sobie z awarią serwera wymaga replikacji, a to jest bardzo trudne do wykonania (patrz literatura na temat algorytmu Paxos, aby dowiedzieć się, dlaczego budowanie konsensusu jest niezręczne) i jest również dość powolne. Co więcej, jeśli wszystkie serwery są nieosiągalne z określonej części sieci, żaden z klientów podłączonych do tej podsieci nie będzie w stanie nic zrobić, ponieważ wszyscy będą czekać na nowe identyfikatory.
Więc ... użyj prostego algorytmu probabilistycznego, aby wygenerować je, które prawdopodobnie nie zawiodą podczas życia Ziemi, lub (sfinansuj i) zbuduj główną infrastrukturę, która będzie wdrożeniem PITA i będzie miała częste awarie. Wiem, na który wybrałbym.
źródło
nie rozumiem wszystkiego o prawdopodobieństwie kolizji. Nie obchodzi mnie kolizja. Ale zależy mi na wydajności.
https://dba.stackexchange.com/a/119129/33649
źródło
Jeśli spojrzysz tylko na alternatywy, np. Prostą aplikację bazodanową, aby za każdym razem przed utworzeniem nowego obiektu musieć przesyłać zapytania do bazy danych, szybko przekonasz się, że użycie UUID może skutecznie zredukować złożoność systemu. Granted - jeśli używasz kluczy int, są 32-bitowe, które będą przechowywać w jednej czwartej 128-bitowego UUID. To prawda - algorytmy generujące UUID zajmują więcej mocy obliczeniowej niż zwykłe zwiększanie liczby. Ale kogo to obchodzi? Narzut związany z zarządzaniem „organem” w celu przypisania unikalnych numerów łatwo przeważa o rzędy wielkości, w zależności od zamierzonego obszaru identyfikatora unikalności.
źródło
Na UUID == leniwy projekt
Nie zgadzam się, że chodzi o wybieranie twoich walk. Jeśli duplikat UUID jest statystycznie niemożliwy, a matematyka została udowodniona, to po co się martwić? Poświęcanie czasu na projektowanie wokół małego systemu generującego N UUID jest niepraktyczne, zawsze istnieje tuzin innych sposobów na ulepszenie systemu.
źródło
W mojej ostatniej pracy otrzymywaliśmy od stron trzecich przedmioty, które były jednoznacznie identyfikowane za pomocą UUID. Umieściłem w tabeli wyszukiwania UUID-> długie liczby całkowite i użyłem długich liczb całkowitych jako moich kluczy podstawowych, ponieważ w ten sposób było o wiele szybciej.
źródło
Korzystając z algorytmu wersji 1 wydaje się, że kolizja jest niemożliwa pod warunkiem, że mniej niż 10 UUID na milisekundę jest generowanych z tego samego adresu MAC
Niech ktoś mnie poprawi, jeśli źle zinterpretowałem, jak to działa
źródło
Do tych, którzy twierdzą, że identyfikatory UUID są złym projektem, ponieważ mogą (z jakimś śmiesznie małym prawdopodobieństwem) kolidować, podczas gdy klucze wygenerowane przez bazę danych nie będą ... znacie możliwość wystąpienia błędu ludzkiego powodującego kolizję kluczy wygenerowanych -przeznaczona potrzeba jest DUŻO DUŻO większa niż prawdopodobieństwo kolizji UUID4. Wiemy , że jeśli baza danych zostanie odtworzona, identyfikatory ponownie zaczną się od 1, a ilu z nas musiało odtworzyć tabelę, gdy byliśmy pewni, że nigdy nie będziemy tego potrzebować? Postawiłbym pieniądze na bezpieczeństwo UUID, gdy coś zacznie się nie udać z nieznanymi-niewiadomymi.
źródło
Oprócz przypadków, w których musisz użyć cudzego API, które wymaga identyfikatora UUID, oczywiście zawsze istnieje inne rozwiązanie. Ale czy te alternatywy rozwiążą wszystkie problemy, które powodują identyfikatory UUID? Czy w końcu dodasz więcej warstw hacków, z których każda ma rozwiązać inny problem, podczas gdy mógłbyś rozwiązać je wszystkie naraz?
Tak, teoretycznie istnieje możliwość kolizji identyfikatorów UUID. Jak zauważyli inni, jest to absurdalnie nieprawdopodobne do tego stopnia, że po prostu nie warto się nad tym zastanawiać. To się nigdy nie zdarzyło i najprawdopodobniej nigdy nie będzie. Zapomnij o tym.
Najbardziej „oczywistym” sposobem uniknięcia kolizji jest pozwolenie pojedynczemu serwerowi na generowanie unikalnych identyfikatorów dla każdej wkładki, co oczywiście stwarza poważne problemy z wydajnością i nie rozwiązuje w ogóle problemu generowania offline. Ups.
Innym „oczywistym” rozwiązaniem jest centralny organ, który z wyprzedzeniem rozdaje bloki unikalnych numerów, co jest zasadniczo tym, co robi UUID V1, wykorzystując adres MAC maszyny generującej (za pośrednictwem IEEE OUI). Jednak zduplikowane adresy MAC zdarzają się, ponieważ każdy organ centralny w końcu spieprzy, więc w praktyce jest to znacznie bardziej prawdopodobne niż kolizja UUID V4. Ups.
Najlepszym argumentem przeciwko używaniu identyfikatorów UUID jest to, że są one „zbyt duże”, ale (znacznie) mniejszy schemat nieuchronnie nie rozwiąże najciekawszych problemów; Rozmiar identyfikatorów UUID jest nieodłącznym efektem ubocznym ich przydatności w rozwiązywaniu tych właśnie problemów.
Możliwe, że Twój problem nie jest wystarczająco duży, aby potrzebować tego, co oferują identyfikatory UUID, w takim przypadku możesz użyć czegoś innego. Ale jeśli twój problem nieoczekiwanie narasta (a większość tak się dzieje), później zmienisz się na inne - i skopiesz się za to, że ich nie używasz. Po co projektować pod kątem porażki, skoro równie łatwo jest projektować pod kątem sukcesu?
źródło
Identyfikatory UUID obejmują wszystkie złe praktyki kodowania związane ze zmiennymi globalnymi, tylko gorzej, ponieważ są to zmienne superglobalne, które można rozłożyć na różne elementy zestawu.
Niedawno natrafiłem na taki problem z wymianą drukarki na dokładny model zastępczy i stwierdziłem, że żadne oprogramowanie klienckie nie będzie działać.
źródło