Saya tahu bahwa UUID acak memiliki probabilitas yang sangat, sangat, sangat rendah untuk tabrakan secara teori, tetapi saya bertanya-tanya, dalam praktiknya, seberapa baik Java randomUUID()
dalam hal tidak memiliki tabrakan? Adakah yang punya pengalaman untuk dibagikan?
311
Jawaban:
Penggunaan UUID
java.security.SecureRandom
, yang seharusnya "kuat secara kriptografi". Sementara implementasi aktual tidak ditentukan dan dapat bervariasi di antara JVM (artinya setiap pernyataan konkret yang dibuat hanya valid untuk satu JVM tertentu), itu mengamanatkan bahwa output harus lulus uji generator angka acak statistik.Selalu mungkin bagi suatu implementasi untuk mengandung bug halus yang merusak semua ini (lihat bug pembangkitan kunci OpenSSH) tapi saya tidak berpikir ada alasan konkret untuk khawatir tentang keacakan Java UUID.
sumber
Wikipedia memiliki jawaban yang sangat bagus http://en.wikipedia.org/wiki/Universally_unique_identifier#Collisions
sumber
UUID.randomUUID()
, bukan tentang peluang teoretis untuk generator angka acak sempurna yang diberikan.Ada
2^122
nilai yang mungkin untuk UUID tipe-4. (Spesifikasi mengatakan bahwa Anda kehilangan 2 bit untuk tipe, dan 4 bit lebih lanjut untuk nomor versi.)Dengan asumsi bahwa Anda menghasilkan 1 juta UUID acak per detik, kemungkinan duplikat yang terjadi dalam hidup Anda akan semakin kecil. Dan untuk mendeteksi duplikat, Anda harus menyelesaikan masalah dengan membandingkan 1 juta UUID baru per detik dengan semua UUID yang sebelumnya Anda hasilkan 1 !
Peluang yang pernah dialami seseorang (yaitu benar-benar diperhatikan ) duplikat dalam kehidupan nyata bahkan lebih kecil daripada semakin kecil ... karena kesulitan praktis dalam mencari tabrakan.
Sekarang tentu saja, Anda biasanya akan menggunakan generator angka pseudo-acak, bukan sumber angka yang benar-benar acak. Tapi saya pikir kita bisa yakin bahwa jika Anda menggunakan penyedia yang dapat dikreditkan untuk angka acak kekuatan kriptografis Anda, maka itu akan menjadi kekuatan kriptografi, dan kemungkinan pengulangan akan sama seperti untuk generator nomor acak yang ideal (tidak bias). .
Namun, jika Anda menggunakan JVM dengan generator nomor crypto-random yang "rusak", semua taruhan dimatikan. (Dan itu mungkin termasuk beberapa solusi untuk masalah "kekurangan entropi" pada beberapa sistem. Atau kemungkinan bahwa seseorang telah bermain-main dengan JRE Anda, baik di sistem Anda atau di hulu.)
1 - Dengan asumsi bahwa Anda menggunakan "semacam binary btree" seperti yang diusulkan oleh komentator anonim, setiap UUID akan membutuhkan
O(NlogN)
bit memori RAM untuk mewakiliN
UUID yang berbeda dengan asumsi kepadatan rendah dan distribusi acak bit. Sekarang kalikan dengan 1.000.000 dan jumlah detik untuk menjalankan eksperimen. Saya tidak berpikir itu praktis untuk lamanya waktu yang dibutuhkan untuk menguji tabrakan RNG berkualitas tinggi. Bahkan dengan representasi pandai (hipotetis).sumber
Saya bukan ahli, tetapi saya berasumsi bahwa cukup banyak orang pintar melihat generator angka acak Jawa selama bertahun-tahun. Oleh karena itu, saya juga berasumsi bahwa UUID acak itu baik. Jadi Anda harus benar-benar memiliki probabilitas tumbukan teoritis (yaitu sekitar 1: 3 × 10 ^ 38 untuk semua UUID yang mungkin. Apakah ada yang tahu bagaimana perubahan ini hanya untuk UUID acak? Apakah ini
1/(16*4)
di atas?)Dari pengalaman praktis saya, saya belum pernah melihat tabrakan sejauh ini. Saya mungkin akan menumbuhkan janggut panjang yang mencengangkan pada hari saya mendapatkan yang pertama;)
sumber
Di mantan majikan kami memiliki kolom unik yang berisi uuid acak. Kami mendapat tabrakan pada minggu pertama setelah dikerahkan. Tentu, peluangnya rendah tetapi tidak nol. Itu sebabnya Log4j 2 mengandung UuidUtil.getTimeBasedUuid. Ini akan menghasilkan UUID yang unik selama 8,925 tahun selama Anda tidak menghasilkan lebih dari 10.000 UUID / milidetik pada server tunggal.
sumber
Skema generasi asli untuk UUID adalah untuk menyatukan versi UUID dengan alamat MAC komputer yang menghasilkan UUID, dan dengan jumlah interval 100 nanodetik sejak adopsi kalender Gregorian di Barat. Dengan mewakili satu titik dalam ruang (komputer) dan waktu (jumlah interval), peluang tabrakan nilai secara efektif adalah nihil.
sumber
Banyak jawaban membahas berapa banyak UUID yang harus dihasilkan untuk mencapai kemungkinan tabrakan 50%. Tapi kemungkinan tabrakan 50%, 25%, atau bahkan 1% tidak berguna untuk aplikasi di mana tabrakan harus (secara virtual) tidak mungkin.
Apakah pemrogram secara rutin menganggap sebagai "tidak mungkin" peristiwa lain yang dapat dan memang terjadi?
Ketika kita menulis data ke disk atau memori dan membacanya kembali, kita menerima begitu saja bahwa datanya benar. Kami mengandalkan koreksi kesalahan perangkat untuk mendeteksi adanya korupsi. Tetapi kemungkinan kesalahan yang tidak terdeteksi sebenarnya sekitar 2 -50 .
Tidakkah masuk akal untuk menerapkan standar yang serupa dengan UUID acak? Jika ya, Anda akan menemukan bahwa tabrakan "tidak mungkin" dimungkinkan dalam koleksi sekitar 100 miliar UUID acak (2 36,5 ).
Ini adalah angka astronomi, tetapi aplikasi seperti penagihan terperinci dalam sistem layanan kesehatan nasional, atau pencatatan data sensor frekuensi tinggi pada sejumlah besar perangkat pasti dapat mencapai batas ini. Jika Anda menulis Panduan Hitchhiker berikutnya untuk Galaxy, jangan mencoba untuk menetapkan UUID untuk setiap artikel!
sumber
Karena sebagian besar jawaban berfokus pada teori, saya pikir saya dapat menambahkan sesuatu ke dalam diskusi dengan memberikan tes praktis yang saya lakukan. Dalam database saya, saya memiliki sekitar 4,5 juta UUID yang dihasilkan menggunakan Java 8 UUID.randomUUID (). Berikut ini adalah beberapa yang saya temukan:
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
Jika itu benar-benar acak, kemungkinan memiliki UUID serupa semacam ini akan sangat rendah (lihat edit), karena kami hanya mempertimbangkan 4,5 juta entri. Jadi, meskipun fungsi ini baik, dalam hal tidak memiliki tabrakan, bagi saya itu tidak tampak bahwa baik karena akan dalam teori.
Edit :
Banyak orang tampaknya tidak memahami jawaban ini jadi saya akan menjelaskan maksud saya: Saya tahu bahwa kesamaannya "kecil" dan jauh dari tabrakan penuh. Namun, saya hanya ingin membandingkan UUID.randomUUID () Java dengan generator nomor acak yang sebenarnya, yang merupakan pertanyaan sebenarnya.
Dalam penghasil bilangan acak sejati, probabilitas kasus terakhir terjadi adalah sekitar = 0,007%. Karena itu, saya pikir kesimpulan saya benar.
Formula dijelaskan dalam artikel wiki ini en.wikipedia.org/wiki/Birthday_problem
sumber
Saya bermain lotere tahun lalu, dan saya tidak pernah menang .... tetapi tampaknya lotere memiliki pemenang ...
doc: http://tools.ietf.org/html/rfc4122
Tipe 1: tidak diterapkan. tabrakan dimungkinkan jika uuid dihasilkan pada saat yang sama. impl dapat disinkronkan secara artifisial untuk mem-bypass masalah ini.
Tipe 2: tidak pernah melihat implementasi.
Tipe 3: hash md5: kemungkinan tabrakan (128 bit-2 byte teknis)
Tipe 4: acak: kemungkinan tabrakan (seperti lotere). perhatikan bahwa jdk6 impl tidak menggunakan "benar" secure random karena algoritma PRNG tidak dipilih oleh pengembang dan Anda dapat memaksa sistem untuk menggunakan algo PRNG "buruk". Jadi UUID Anda bisa ditebak.
Tipe 5: sha1 hash: tidak diimplementasikan: kemungkinan collision (160 bit-2 byte teknis)
sumber
Kami telah menggunakan UUID acak Java dalam aplikasi kami selama lebih dari satu tahun dan itu sangat luas. Tapi kami tidak pernah menemukan tabrakan.
sumber