Kiedy należy używać uuid.uuid1 () vs.uuid.uuid4 () w Pythonie?

Rozumiem różnice między tymi dwoma z dokumentów.

uuid1():
Generuje UUID z identyfikatora hosta, numeru sekwencji i bieżącego czasu

uuid4():
Wygeneruj losowy UUID.

Więc uuid1 używa informacji o maszynie/sekwencji/czasie do generowania UUID. Jakie są plusy i minusy używania każdego z nich?

Wiem, że może mieć problemy z prywatnością, ponieważ opiera się na informacjach o maszynach. Zastanawiam się, czy nie ma bardziej subtelnych przy wyborze jednego lub inne. Używam uuid4() teraz, ponieważ jest to całkowicie losowy UUID. Ale zastanawiam się, czy powinienem używać uuid1, aby zmniejszyć ryzyko kolizji.

Zasadniczo, Szukam wskazówek dla ludzi najlepszych praktyk na temat korzystania z jednego vs. drugi. Dzięki!

 182
Author: guettli, 2009-11-23

6 answers

uuid1() gwarantuje, że nie spowoduje żadnych kolizji (przy założeniu, że nie tworzy się ich zbyt wielu w tym samym czasie). Nie używałbym go, jeśli ważne jest, aby nie było połączenia między uuid a komputerem, ponieważ adres mac jest używany, aby uczynić go unikalnym na wszystkich komputerach.

Można tworzyć duplikaty tworząc więcej niż 214 uuid1 w mniej niż 100ns, ale nie jest to problem dla większości przypadków użycia.

uuid4() generuje, jak powiedziałeś, losowy UUID. Szansa na kolizję jest naprawdę, naprawdę, naprawdę naprawdę mała. Na tyle mały, że nie powinieneś się o to martwić. Problem w tym, że zły generator liczb losowych sprawia, że bardziej prawdopodobne jest zderzenie.

Doskonała odpowiedź Boba Amana ładnie to podsumowuje. (Polecam przeczytać całą odpowiedź.)

Szczerze mówiąc, w jednej przestrzeni aplikacji bez złośliwych aktorów, wymieranie wszelkiego życia na ziemi będzie wystąpić na długo przed kolizja, nawet na uuid wersji 4, nawet jeśli generujesz sporo UUIDs na sekundę.

 229
Author: Georg Schölly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:07

Jednym z przypadków, gdy można rozważyć uuid1() zamiast uuid4() jest , gdy uuid są produkowane na oddzielnych maszynach, na przykład, gdy na kilku maszynach przetwarzanych jest wiele transakcji online w celu skalowania.

W takiej sytuacji ryzyko kolizji spowodowane na przykład słabym wyborem w sposobie inicjowania generatorów liczb pseudolosowych, a także potencjalnie większa liczba wytwarzanych uuid, zwiększa prawdopodobieństwo utworzenia duplikaty identyfikatorów.

Innym zainteresowaniem uuid1(), w tym przypadku jest to, że maszyna, na której każdy GUID został pierwotnie wytworzony, jest domyślnie rejestrowana (w części" węzła " UUID). To i informacje o czasie mogą pomóc, jeśli tylko w debugowaniu.

 30
Author: mjv,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-29 05:16:57

Mój zespół wpadł w kłopoty, używając UUID1 do skryptu aktualizacji bazy danych, w którym wygenerowaliśmy ~120k uuid w ciągu kilku minut. Kolizja UUID doprowadziła do naruszenia głównego ograniczenia klucza.

Zaktualizowaliśmy 100 serwerów, ale na instancjach Amazon EC2 napotkaliśmy ten problem kilka razy. Podejrzewam słabą rozdzielczość zegara i przejście na UUID4 rozwiązało to za nas.

 12
Author: Mattias Lagergren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-21 08:51:22

Należy zwrócić uwagę na jedną rzecz przy użyciu uuid1, jeśli używasz domyślnego wywołania (bez podawania parametru clock_seq), masz szansę na kolizję: masz tylko 14 bitów losowości (generowanie 18 wpisów w ciągu 100ns daje około 1% szansy na kolizję patrz paradoks/atak urodzinowy). Problem nigdy nie wystąpi w większości przypadków użycia, ale na maszynie wirtualnej ze słabą rozdzielczością zegara ugryzie cię.

 5
Author: Guillaume,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-17 18:49:50

Być może coś, o czym nie wspomniano, to miejsce.

Adres MAC lub kolejność oparta na czasie (UUID1) może pozwolić sobie na zwiększenie wydajności bazy danych, ponieważ sortowanie liczb jest mniej pracy niż sortowanie liczb rozproszonych losowo (UUID4) (Zobacz TUTAJ).

Drugi powiązany problem polega na tym, że używanie UUID1 może być przydatne w debugowaniu, nawet jeśli dane pochodzenia są utracone lub nie są bezpośrednio przechowywane (jest to oczywiście sprzeczne z kwestią prywatności wspomnianą przez OP).

 3
Author: c z,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 16:46:30

Oprócz zaakceptowanej odpowiedzi, istnieje trzecia opcja, która może być przydatna w niektórych przypadkach:

V1 z losowym MAC ("v1mc")

Możesz utworzyć hybrydę między v1 i v4, celowo generując uuid v1 z losowym adresem MAC (jest to dozwolone przez specyfikację v1). Wynikowy UUID v1 jest zależny od czasu (jak zwykły v1), ale nie zawiera wszystkich informacji specyficznych dla hosta (jak v4). Jest również znacznie bliżej v4 w swojej odporności na kolizje: v1mc = 60 bitów czasu + 61 losowych bits = 121 unikalnych bitów; v4 = 122 losowe bity.

Pierwszym miejscem, z którym się spotkałem, była funkcja Postgres' uuid_generate_v1mc(). Od tego czasu używałem następującego odpowiednika Pythona:

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)

(Uwaga: mam dłuższą + szybszą wersję, która bezpośrednio tworzy obiekt UUID; może pisać, jeśli ktoś chce)


W przypadku dużych ilości wywołań / sekundę, ma to potencjał do losowości układu. Możesz użyć modułu stdlib random zamiast tego (prawdopodobnie będzie też szybciej). Uwaga: atakujący może określić stan RNG, a tym samym częściowo przewidzieć przyszłe uuid, potrzeba tylko kilkuset uuid.

import random
from uuid import uuid1

def uuid1mc_insecure():
    return uuid1(random.getrandbits(48) | 0x010000000000)
 0
Author: Eli Collins,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-22 16:15:02