Uuid.uuid1 () ile uuid.uuid4 () ne zaman python'da kullanmalıyım?


207

İkisi arasındaki dokümanlar arasındaki farkları anlıyorum .

uuid1():
Ana bilgisayar kimliğinden, sıra numarasından ve geçerli saatten bir UUID oluşturma

uuid4():
Rastgele bir UUID oluşturun.

Bu yüzden uuid1bir UUID oluşturmak için makine / sıra / zaman bilgisini kullanır. Her birini kullanmanın avantajları ve dezavantajları nelerdir?

uuid1()Makine bilgilerine dayandığı için gizlilik endişeleri olabileceğini biliyorum . Birini seçerken daha incelikli olup olmadığını merak ediyorum. Sadece uuid4()şu anda kullanıyorum, çünkü tamamen rastgele bir UUID. Ama uuid1çarpışma riskini azaltmak için kullanmalı mıyım diye merak ediyorum .

Temel olarak, insanların birini diğerine karşı kullanma konusunda en iyi uygulamalar için ipuçlarını arıyorum. Teşekkürler!


3
İşte UUID'ye alternatif bir yaklaşım. Çarpışma şansı sonsuz olsa da, UUID benzersizliğini garanti etmez. Benzersizliği garanti etmek için [<system id>, <local id>] olarak bileşik anahtar kullanmak isteyebilirsiniz. Veri paylaşımına katılan her sistemin, sistem kurulumu sırasında atanan veya ortak bir kimlik havuzundan elde edilen kendi benzersiz sistem kimliği olmalıdır. Yerel kimlik, herhangi bir sistemdeki benzersiz bir kimliktir. Bu daha fazla güçlük içerir, ancak benzersizliği garanti eder. Offtopik için üzgünüm, sadece yardım etmeye çalışıyorum.
o

3
Bahsettiği "gizlilik endişeleri" ile
ilgilenmez

Yanıtlar:


253

uuid1()herhangi bir çarpışma oluşturmayacağı garanti edilir (aynı anda çok fazla yaratmadığınız varsayımı altında). uuidMac adresi bilgisayarlar arasında benzersiz kılmak için kullanıldığından, bilgisayar ile arasında bir bağlantı olmaması önemliyse kullanmazdım .

100ns'den daha az bir sürede 2 14 uuid1'den daha fazlasını oluşturarak kopyalar oluşturabilirsiniz , ancak bu çoğu kullanım durumunda sorun değildir.

uuid4()Dediğiniz gibi rastgele bir UUID üretir. Çarpışma şansı gerçekten, gerçekten, gerçekten küçük. Bu konuda endişelenmemeniz için yeterince küçük. Sorun, kötü bir rasgele sayı üretecinin çarpışma olasılığını artırmasıdır.

Bob Aman'ın bu mükemmel cevabı güzelce özetliyor. (Bütün cevabı okumanızı tavsiye ederim.)

Açıkçası, kötü niyetli aktörlerin olmadığı tek bir uygulama alanında, saniyede birkaç UUID üretiyor olsanız bile, 4 UUID sürümünde bile, bir çarpışmadan çok önce, dünyadaki tüm yaşamın yok olması gerçekleşecektir.


Üzgünüz, tamamen araştırma yapmadan yorum yaptım - sürüm 4 uuid sürüm 1 uuid ile çarpışmasını önlemek için ayrılmış bit vardır. Orijinal yorumumu kaldıracağım. Bkz. Tools.ietf.org/html/rfc4122
Mark Ransom

1
@gs Evet, okuduğum şeyle mantıklı. uuid1 "daha benzersiz", uuid4 ise daha anonimdir. Bu yüzden temelde uuid1'i kullanmamanız için bir nedeniniz yoksa kullanın. @mark fidye: Harika cevap, uuid1 / uuid4 aradığımda gelmedi. Atın ağzından düz görünüyor.
rocketmonkeys

6
uuid1aynı düğümde saniyede birkaç tane üretirseniz mutlaka benzersiz UUID'ler üretmez. Örnek: [uuid.uuid1() for i in range(2)]. Tabii ki garip bir şey olmadığı sürece eksik olduğum.
Michael Mior

1
@Michael: uuid1bir sıra numarasına sahiptir (örneğinizde 4. eleman), bu nedenle sayaçtaki tüm bitleri kullanmazsanız herhangi bir çarpışma olmaz.
Georg Schölly

3
@Michael: Çarpışmaların olduğu koşulları araştırmayı denedim ve bulduğum bilgileri ekledim.
Georg Schölly

32

Eğer düşünebilir Bir örneği uuid1()yerine uuid4()ise Uuıdlerin ayrı makinelerde üretilen zaman birden fazla çevrimiçi işlemler ölçeklendirme amacıyla birçok makineye sürecini olduğunda örneğin.

Böyle bir durumda, örneğin sözde rasgele sayı üreteçlerinin başlatılma biçimindeki zayıf seçimler nedeniyle çarpışma riskleri ve ayrıca üretilen potansiyel olarak daha yüksek sayıda UUID, yinelenen kimlikler oluşturma olasılığını arttırır.

uuid1()Bu durumda bir başka ilgi, her GUID'nin başlangıçta üretildiği makinenin dolaylı olarak kaydedilmesidir (UUID'nin "düğüm" kısmında). Bu ve zaman bilgisi, sadece hata ayıklama ile yardımcı olabilir.


20

Ekibim, birkaç dakika içinde ~ 120 bin UUID oluşturduğumuz bir veritabanı yükseltme komut dosyası için UUID1'i kullanmada sorun yaşadı. UUID çarpışması birincil anahtar kısıtlamasının ihlaline yol açtı.

100'lü sunucuyu yükselttik, ancak Amazon EC2 bulut sunucularımızda bu sorunla birkaç kez karşılaştık. Zayıf saat çözünürlüğünden şüpheleniyorum ve UUID4'e geçmek bizim için çözdü.


5

Kullanırken dikkat edilmesi gereken bir şey uuid1, varsayılan çağrıyı kullanırsanız ( clock_seqparametre vermeden ) çarpışmalara girme şansınız vardır: sadece 14 bit rasgele (100ns içinde 18 giriş oluşturmak size yaklaşık% 1 çarpışma şansı verir) doğum günü paradoksu / saldırısı). Sorun çoğu kullanım durumunda asla ortaya çıkmaz, ancak saat çözünürlüğünün düşük olduğu bir sanal makinede sizi ısıracaktır.


7
@Guilaume kullanarak iyi bir uygulama örneği görmek gerçekten yararlı olacaktır clock_seq....
eric

@Guilaume Bu% 1 şansı nasıl hesapladınız? 14 bit rasgelelik, 100ns başına> = 2 ^ 14 id ürettiğinizde çarpışma gerçekleşeceği anlamına gelir ve bu da 100 ns başına kabaca 163 id ürettiğinizde çarpışma olasılığının% 1 olduğu anlamına gelir
maks

1
@maks Dediğim gibi, doğum günü paradoksuna bakmalısın .
Guillaume

3

Belki de bahsedilmeyen bir şey yerelliktir.

MAC adresi veya zamana dayalı sipariş verme (UUID1), rastgele dağıtılanlardan (UUID4) sayıları birbirine daha yakın sıralamak için daha az iş olduğundan, artan veritabanı performansı sağlayabilir ( buraya bakın ).

İkinci bir ilgili sorun, UUID1 kullanımının, başlangıç ​​noktası verileri kaybolsa veya açıkça depolanmasa bile hata ayıklamada yararlı olabilmesidir (bu açıkça OP tarafından belirtilen gizlilik sorunuyla çelişmektedir).


1

Kabul edilen cevaba ek olarak, bazı durumlarda yararlı olabilecek üçüncü bir seçenek vardır:

rasgele MAC ile v1 ("v1mc")

Kasıtlı olarak rastgele bir yayın MAC adresi ile v1 UUID'ler oluşturarak v1 ve v4 arasında bir karma oluşturabilirsiniz (buna v1 özellikleri tarafından izin verilir). Ortaya çıkan v1 UUID, zamana bağımlıdır (normal v1 gibi), ancak ana bilgisayara özgü tüm bilgilerden (v4 gibi) yoksundur. Ayrıca çarpışma direncinde v4'e çok daha yakın: v1mc = 60 bit zaman + 61 rastgele bit = 121 benzersiz bit; v4 = 122 rastgele bit.

Bu karşılaştığım ilk yer Postgres ' uuid_generate_v1mc () işlevi oldu. O zamandan beri aşağıdaki python eşdeğerini kullandım:

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)

(not: UUID nesnesini doğrudan oluşturan daha uzun + daha hızlı bir sürümüm var; isterse gönderebilir)


BÜYÜK ses seviyesi / saniye olması durumunda, bu durum sistemin rasgeleliğini tüketme potansiyeline sahiptir. Sen olabilir stdlib kullanmak random(muhtemelen de daha hızlı olacaktır) yerine modülü. Ancak UYARI: Bir saldırganın RNG durumunu belirlemesi ve böylece gelecekteki UUID'leri kısmen tahmin etmesi yalnızca birkaç yüz UUID alır.

import random
from uuid import uuid1

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

Bu yöntemin v4 (host-agnostic) gibi "kötü", fakat daha kötü (daha az bit, urandom bağımlılığı vb.) Gibi görünmektedir. Sadece uuid4 ile karşılaştırıldığında herhangi bir avantajı var mı?
rocketmonkeys

Bu, v1'in zamana dayalı nitelikleri için yararlı olduğu, ancak daha güçlü çarpışma direnci ve ana bilgisayar gizliliğinin istendiği durumlar için sadece bir yükseltmedir. Bir örnek, bir veritabanı için birincil anahtardır - v4 ile karşılaştırıldığında, v1 uuids, diske yazarken daha iyi bir konuma sahip olacak, daha yararlı bir doğal sıralamaya sahip olacak, ancak. Bir saldırganın 2 ** 61 bit bir güvenlik sorunu (örneğin uuid bir nonce gibi), sonra $ diety evet, bunun yerine uuid4 kullanın (biliyorum biliyorum!). Re: daha kötü olmak urandom kullandığından, ne demek istediğinden emin değilim - python altında uuid4 () de urandom kullanır.
Eli Collins

İyi şeyler, bu mantıklı. Sadece ne yapabileceğinizi (kodunuzu) değil, aynı zamanda neden istediğinizi de görmek güzel. Re: urandom, yani rastgele 2x (uuid1 için 1, urandom için başka) tüketiyorsunuz, bu yüzden sistem entropisini daha hızlı tüketebilirsiniz.
rocketmonkeys

Aslında uuid4'ün yaklaşık yarısı kadardır: uuid1 () clock_seq için 2 bit urandom'a kadar yuvarlayan 14 bit kullanır. Uuid1mc sarıcısı, arama başına tüketilen toplam urandom (8) için 6 bayt urandom ile eşleşmesi gereken 48 bit kullanır. oysa uuid4 her çağrı için doğrudan urandomu (16) çağırır.
Eli Collins
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.