Randomize UUID'lerin teoride çarpışma olasılığı çok, çok, çok düşük olduğunu biliyorum , ama pratikte Java'nın randomUUID()
çarpışma olmaması açısından ne kadar iyi olduğunu merak ediyorum ? Paylaşacak herhangi bir tecrübesi olan var mı?
Randomize UUID'lerin teoride çarpışma olasılığı çok, çok, çok düşük olduğunu biliyorum , ama pratikte Java'nın randomUUID()
çarpışma olmaması açısından ne kadar iyi olduğunu merak ediyorum ? Paylaşacak herhangi bir tecrübesi olan var mı?
Yanıtlar:
java.security.SecureRandom
"Kriptografik olarak güçlü" olması gereken UUID kullanır . Gerçek uygulama belirtilmemiş ve JVM'ler arasında değişiklik gösterebilse de (yapılan somut ifadelerin yalnızca belirli bir JVM için geçerli olduğu anlamına gelir), çıktının istatistiksel rasgele sayı üreteci testini geçmesi zorunludur.
Bir uygulamanın her şeyi mahveden ince hatalar içermesi her zaman mümkündür (bkz. OpenSSH anahtar oluşturma hatası), ancak Java UUID'lerin rastgeleliği hakkında endişelenmenin somut bir nedeni olduğunu düşünmüyorum.
Vikipedi'nin çok iyi bir cevabı var http://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions
en az bir çarpışma olasılığının% 50 olması için üretilmesi gereken rastgele sürüm 4 UUID'lerin sayısı aşağıdaki şekilde hesaplanır: 2.71 quintillion:
...
Bu sayı, yaklaşık 85 yıl boyunca saniyede 1 milyar UUID oluşturmaya eşdeğerdir ve UUID başına 16 baytta bu çok sayıda UUID içeren bir dosya, şu anda var olan en büyük veritabanlarından birçok kez daha büyük olmak üzere yaklaşık 45 eksabayt olacaktır. yüzlerce petabayt sırası.
...
Bu nedenle, milyarlarca çoğaltma şansı olması için 103 trilyon sürüm 4 UUID oluşturulmalıdır.
UUID.randomUUID()
belirli bir rasgele sayı üretecinin teorik şansı hakkında değil , Java'lardaki rasgeleliğin kalitesi ile ilgilidir .
Paylaşacak herhangi bir tecrübesi olan var mı?
2^122
Tip 4 UUID için olası değerler vardır . (Spesifikasyon, tür için 2 bit ve sürüm numarası için 4 bit daha kaybettiğinizi söylüyor.)
Saniyede 1 milyon rastgele UUID üreteceğinizi varsayarsak, yaşamınızda yinelenen bir şansın olması kaybolur. Ve yinelenen algılamak için, size karşı saniyede 1 milyon yeni UUIDs karşılaştırmanın sorunu çözmek zorundayız önceden oluşturmuş UUID tüm 1 !
Herkesin gerçek hayatta bir kopyasını yaşamış olma (yani aslında farkına varma ) şansı, çarpışmayı aramanın pratik zorluğu nedeniyle, kaybolan küçüklükten bile daha küçüktür.
Şimdi, elbette, gerçekten rastgele sayıların kaynağı değil, tipik olarak sahte bir sayı üreteci kullanacaksınız. Ancak, kriptografik güç rasgele sayılarınız için güvenilir bir sağlayıcı kullanıyorsanız, o zaman kriptografik güç olacağından ve tekrarlama olasılığının ideal (önyargısız) rasgele sayı üreteciyle aynı olacağından emin olabiliriz. .
Ancak, "bozuk" kripto rasgele sayı üreteciyle bir JVM kullanacaksanız, tüm bahisler kapalıdır. (Bu, bazı sistemlerde "entropi kıtlığı" sorunları için bazı geçici çözümleri de içerebilir. Veya birisinin JRE'nizle sisteminizde veya yukarı akışta uğraşma olasılığı.)
1 - Anonim bir yorumcu tarafından önerildiği gibi "bir tür ikili btree" kullandığınızı varsayarsak, her UUID'nin, O(NlogN)
bitlerin N
düşük yoğunluğu ve rastgele dağılımını varsayan farklı UUID'leri temsil etmek için RAM bellek parçalarına ihtiyacı olacaktır . Şimdi bunu 1.000.000 ile ve denemeyi yapacağınız saniye sayısını çarpın. Bunun yüksek kaliteli RNG çarpışmalarını test etmek için gereken süre boyunca pratik olduğunu düşünmüyorum. (Varsayımsal) akıllı temsillerle bile değil.
Ben bir uzman değilim, ama yıllarca Java'nın rasgele sayı üreticisine bakacak kadar zeki insan olduğunu varsayıyorum. Bu nedenle, rastgele UUID'lerin de iyi olduğunu varsayabilirim. Bu yüzden gerçekten teorik çarpışma olasılığına sahip olmalısınız (bu, tüm olası UUID'ler için yaklaşık 1: 3 × 10 ^ 38'dir . Herkes bunun rastgele UUID'ler için nasıl değiştiğini biliyor mu 1/(16*4)
?
Pratik tecrübelerime göre, şimdiye kadar hiç çarpışma görmedim. Muhtemelen ilkini aldığım gün şaşırtıcı derecede uzun sakal bırakacağım;)
Eski bir işverenimizde rastgele bir uuid içeren benzersiz bir sütun vardı. Konuşlandırıldıktan sonraki ilk hafta bir çarpışma yaşadık. Tabii, oranlar düşük ama sıfır değil. Bu nedenle Log4j 2, UuidUtil.getTimeBasedUuid içeriyor. Tek bir sunucuda 10.000'den fazla UUID / milisaniyeden fazla üretmediğiniz sürece 8.925 yıl boyunca benzersiz bir UUID üretecektir.
UUID'ler için orijinal nesil şeması, UUID sürümünü, UUID'yi oluşturan bilgisayarın MAC adresiyle ve Batı'da Gregoryen takviminin benimsenmesinden bu yana 100 nanosaniye aralıklarla birleştirmekti. Uzayda tek bir noktayı (bilgisayar) ve zamanı (aralık sayısı) temsil ederek, değerlerde çarpışma olasılığı etkin bir şekilde sıfırdır.
Yanıtların çoğu,% 50'lik bir çarpışma şansına ulaşmak için kaç tane UUID'nin oluşturulması gerektiğini tartışıyor. Ancak, çarpışmanın (neredeyse) imkansız olması gereken bir uygulama için% 50,% 25 ve hatta% 1 çarpışma şansı değersizdir.
Programcılar rutin olarak meydana gelebilecek ve meydana gelebilecek diğer olayları "imkansız" olarak reddediyor mu?
Bir diske veya belleğe veri yazıp tekrar okuduğumuzda, verilerin doğru olduğunu kabul ederiz. Herhangi bir bozulmayı tespit etmek için cihazın hata düzeltmesine güveniyoruz. Ancak saptanamayan hataların olasılığı aslında 2-50 civarındadır .
Rastgele UUID'lere benzer bir standart uygulamak mantıklı değil mi? Bunu yaparsanız, yaklaşık 100 milyar rastgele UUID koleksiyonunda "imkansız" bir çarpışmanın mümkün olduğunu göreceksiniz (2 36.5 ).
Bu bir astronomik sayıdır, ancak ulusal bir sağlık sisteminde ayrıntılı faturalandırma veya yüksek frekans sensör verilerinin çok sayıda cihaza kaydedilmesi gibi uygulamalar kesinlikle bu sınırlara çarpabilir. Bir sonraki Otostopçu Rehberi Galaksiye yazıyorsanız, her makaleye UUID atamaya çalışmayın!
Cevapların çoğu teoriye odaklandığından, pratik bir test yaparak tartışmaya bir şeyler ekleyebileceğimi düşünüyorum. Veritabanımda Java 8 UUID.randomUUID () kullanılarak oluşturulmuş yaklaşık 4,5 milyon UUID var. Aşağıdakiler sadece öğrendiğim bazıları:
c0f55f62 -b990-47bc-8caa-f42313669948
c0f55f62 -e81e-4253-8299-00b4322829d5
c0f55f62 -4979-4e87-8cd9-1c556894e2bb
b9ea2498-fb32-40ef-91ef-0BA 00060fe64
be87a209-2114-45b3-9d5a- 86d 00060fe64
4a8a74a6-e972-4069-b480-b dea1177b21f
12fb4958-bee2-4c89-8cf8-e dea1177b21f
Gerçekten rastgele olsaydı, bu tür benzer UUID'lere sahip olma olasılığı oldukça düşük olurdu (düzenlemeye bakın), çünkü sadece 4,5 milyon girişi düşünüyoruz. Bu işlev değil sahip çarpışmaların açısından iyi olmasına rağmen Yani, benim için o görünmüyor o da teoride olacağı gibi iyi.
Düzenle :
Pek çok insan bu cevabı anlamıyor gibi görünüyor, bu yüzden fikrimi netleştireceğim: Benzerliklerin "küçük" ve tam bir çarpışmadan uzak olduğunu biliyorum. Ancak, sadece Java'nın UUID.randomUUID () gerçek soru rastgele gerçek bir sayı üreteci ile karşılaştırmak istedim.
Gerçek bir rasgele sayı üretecinde, son durumun meydana gelme olasılığı =% 0.007 civarında olacaktır . Bu nedenle, sonucumun geçerli olduğunu düşünüyorum.
Formül bu wiki makalesinde açıklanmıştır. En.wikipedia.org/wiki/Birthday_problem
Geçen yıl piyango oynuyorum ve hiç kazanmadım .... ama piyangonun kazananları var gibi görünüyor ...
doc: http://tools.ietf.org/html/rfc4122
Tip 1: uygulanmadı. uuid aynı anda üretilirse çarpışma mümkündür. impl bu sorunu atlamak için yapay olarak senkronize olabilir.
Tip 2: asla bir uygulama görmeyin.
Tip 3: Md5 karma: olası çarpışma (128 bit-2 teknik bayt)
Tip 4: Rastgele: Çarpışma mümkün (piyango olarak). jdk6 impl "PRNG algoritması geliştirici tarafından seçilmez ve" bir "zayıf" PRNG algo kullanmaya zorlayabilirsiniz çünkü "gerçek" güvenli rasgele kullanmayın unutmayın. Yani UUID'niz tahmin edilebilir.
Tip 5: sha1 karması: uygulanmadı: çarpışma mümkün (160 bit-2 teknik bayt)