Dapat diterima untuk bergantung pada int acak yang unik?


42

Saya telah mengimplementasikan protokol jaringan, dan saya membutuhkan paket untuk memiliki pengidentifikasi unik. Sejauh ini, saya baru saja menghasilkan bilangan bulat 32-bit acak, dan dengan asumsi bahwa secara astronomis tidak mungkin akan ada tabrakan selama umur suatu program / koneksi. Apakah ini secara umum dianggap sebagai praktik yang dapat diterima dalam kode produksi, atau haruskah seseorang membuat sistem yang lebih kompleks untuk mencegah tabrakan?


47
Mengapa menggunakan integer berurutan tidak akan memotongnya?
whatsisname

20
Mengapa Anda tidak menggunakan int tambahan saja? GUIDs , yang dirancang untuk memiliki sifat keunikan yang Anda gambarkan, berukuran 128 bit, bukan 32.
Robert Harvey

21
Atau, tetapkan nomor saluran untuk setiap komputer yang terhubung, dan gunakan id urutan yang bertambah. Dua angka digabungkan (dengan nomor saluran mengambil bit orde tinggi) menjadi id unik baru Anda.
Robert Harvey

27
Jika "generator nomor acak" Anda menjamin bahwa nomor tertentu tidak akan diulang sampai setiap nomor lainnya dihasilkan, itu adalah generator nomor acak yang sangat buruk! Dengan logika yang sama, satu-satunya urutan lemparan koin "acak" yang mungkin adalah HTHTHTHTT ....
alephzero

17
"Saya memerlukan paket untuk memiliki pengidentifikasi unik" Apa konsekuensi dari persyaratan ini yang dilanggar? Jika Anda memerlukan pengidentifikasi unik, dalam pembacaan kata yang paling ketat, Anda harus memiliki sistem terpusat untuk mengidentifikasi pengidentifikasi (seperti bagaimana MAC ditugaskan pada perusahaan kartu jaringan individual). Kemungkinan besar Anda memiliki definisi "persyaratan" yang lebih lunak. Memahami bahwa tingkat kelembutan akan secara dramatis mengubah jawaban yang Anda terima.
Cort Ammon

Jawaban:


142

Waspadai paradoks ulang tahun .

Misalkan Anda menghasilkan urutan nilai acak (seragam, independen) dari satu set ukuran N (N = 2 ^ 32 dalam kasus Anda).

Kemudian, aturan praktis untuk paradoks ulang tahun menyatakan bahwa setelah Anda menghasilkan nilai-nilai sqrt (N), setidaknya ada kemungkinan 50% bahwa tabrakan telah terjadi, yaitu, bahwa setidaknya ada dua nilai identik di urutan yang dihasilkan.

Untuk N = 2 ^ 32, sqrt (N) = 2 ^ 16 = 65536. Jadi setelah Anda menghasilkan sekitar 65k pengidentifikasi, kemungkinan besar keduanya bertabrakan daripada tidak! Jika Anda menghasilkan pengidentifikasi per detik, ini akan terjadi dalam waktu kurang dari sehari; Tak perlu dikatakan, banyak protokol jaringan beroperasi jauh lebih cepat dari itu.


11
+1. Dalam pekerjaan terakhir saya, salah satu mitra kami benar-benar menggunakan pendekatan ini untuk menghasilkan pengidentifikasi acak (bukan untuk paket jaringan, tetapi untuk objek bisnis bersama yang akhirnya dibuat oleh pelanggan akhir). Ketika saya menanyakan data dengan pandangan ke arah ini, saya menemukan bahwa rata-rata, ada dua hingga tiga pasangan duplikat setiap hari. (Untungnya, ini hanya merusak barang-barang jika duplikat itu dibuat dalam waktu empat jam satu sama lain, yang terjadi sedikit lebih sering. Tapi tetap saja.)
ruakh

6
(klik di sini untuk merender matematika) Untuk apa nilainya, perkiraan $ \ sqrt {N} $ akurat hingga faktor konstan; untuk $ N = 2 ^ {32} $, ambang sebenarnya adalah 77164, karena ini adalah nilai terkecil dari $ n $ sehingga $ \ prod_ {k = 1} ^ {n-1} (1 - k / N) <1 / 2. $
wchargin

4
@wchargin: Benar-benar tidak ada yang ajaib tentang kemungkinan memukul 0,5; Apa yang penting adalah bahwa probabilitas meningkat relatif cepat dengan meningkatnya N. Jika pengidentifikasi 32-bit akan memiliki sedikit peluang non-sepele dari tabrakan acak, pengidentifikasi 40-bit hampir tidak akan memiliki.
supercat

3
@ superupat: Itu semua benar. Saya baru saja membayangkan bahwa jika seseorang memberikan konstanta seperti itu, ia mungkin juga memberikan nilai yang akurat :-)
wchargin

2
@wchargin: Saya lebih suka berpikir dalam hal di mana orang perlu mulai khawatir tentang duplikat. Jika seseorang berjalan jauh di bawah sqrt (N) probabilitas tabrakan turun dengan cepat, ke titik di mana seseorang dapat dengan aman mengatakan bahwa itu tidak akan terjadi kecuali jika ada kerusakan parah pada generator acak.
supercat

12

Secara luas dianggap dapat diterima untuk mengandalkan angka acak yang unik jika angka-angka itu memiliki bit yang cukup. Ada protokol kriptografi di mana pengulangan nomor acak akan merusak seluruh keamanan. Dan selama tidak ada kerentanan serius dalam generator angka acak yang digunakan, itu tidak menjadi masalah.

Salah satu algoritma untuk menghasilkan UUID akan secara efektif menghasilkan ID yang terdiri dari 122 bit acak dan menganggapnya unik. Dan dua dari algoritma lainnya bergantung pada nilai hash yang terpotong menjadi 122 bit yang unik, yang memiliki risiko tabrakan yang kira-kira sama.

Jadi ada standar yang mengandalkan 122 bit yang cukup untuk membuat ID acak unik, tetapi 32 bit jelas tidak cukup. Dengan ID 32 bit, hanya dibutuhkan sekitar 2¹⁶ ID sebelum risiko tabrakan mencapai 50% karena dengan 2¹⁶ ID akan ada hampir 2 ³¹ pasangan yang masing-masing bisa berupa tabrakan.

Bahkan 122 bit kurang dari yang saya sarankan dalam desain baru. Jika mengikuti beberapa standardisasi penting bagi Anda, maka gunakan UUID. Kalau tidak gunakan sesuatu yang lebih besar dari 122 bit.

Fungsi hash SHA1 dengan output 160 bit tidak lagi dianggap aman yang sebagian karena 160 bit tidak cukup untuk menjamin keunikan output. Fungsi hash modern memiliki output dari 224 hingga 512 bit. ID yang dihasilkan secara acak harus bertujuan untuk ukuran yang sama untuk memastikan keunikan dengan margin keamanan yang baik.


12
SHA-1 dianggap tidak aman karena ada serangan spesifik (yaitu non-acak) terhadap algoritma itu sendiri yang dapat menemukan tumbukan lebih cepat dari brute force, bukan karena ada kemungkinan besar tumbukan acak. Perkiraan kasar mengatakan bahwa dengan 122 bit dan tingkat generasi 1 miliar (10 ^ 9) ID per detik, itu akan memakan waktu lebih dari 73 tahun sebelum mencapai kemungkinan tabrakan 50%.
8bittree

sqrt(2^122)= 2.3 kuadriliun kuadriliun UUID
noɥʇʎԀʎzɐɹƆ

2
@ 8bittree Jaringan bitcoin menghitung hash 2A SHA2 setiap 10 menit. Seandainya itu hash SHA1, hanya perlu waktu seminggu untuk menghasilkan tabrakan. Jika UUID diproduksi pada kecepatan yang sama dengan bitcoin yang menghitung hash, dibutuhkan waktu kurang dari 2 detik untuk menghasilkan tabrakan.
kasperd

Bitcoin adalah semua tentang mencoba menemukan tabrakan, dan sangat populer dan telah mendedikasikan perangkat keras yang dirancang khusus untuk menemukan hash. Sekarang, tentu saja, jika OP berencana untuk membuat cryptocurrency yang sangat populer, atau yang serupa, maka mereka mungkin membutuhkan ratusan atau ribuan bit per ID. Tetapi dengan segera berasumsi bahwa itu adalah persyaratan mungkin mendorong pekerjaan jauh lebih banyak daripada yang diperlukan jika perpustakaan UUID standar cukup.
8bittree

@ 8bittree Jika menggunakan perpustakaan standar adalah keuntungan, maka tentu saja berlaku untuk UUID. Tetapi mengeluarkan beberapa byte acak urandomtidak lebih berfungsi daripada menggunakan perpustakaan UUID. Saya baru saja mengimplementasikan keduanya dalam Python untuk perbandingan, dan masing-masing metode persis 25 karakter kode sumber.
kasperd

3

Saya akan menyebut praktik buruk ini. Angka acak menghasilkan tidak membuat angka unik, mereka hanya membuat angka acak. Distribusi acak kemungkinan akan menyertakan beberapa duplikat. Anda dapat membuat keadaan ini tidak mungkin diterima dengan menambahkan elemen waktu. Jika Anda mendapatkan waktu saat ini dari jam sistem dalam milidetik. Sesuatu seperti ini:

parseToInt(toString(System.currentTimeMillis()) + toString(Random.makeInt()))

Akan jauh. Jelas untuk benar-benar menjamin keunikan yang Anda butuhkan untuk menggunakan UUID / GUID. Tetapi mereka bisa mahal untuk menghasilkan, di atas kemungkinan cukup, karena satu-satunya kemungkinan tumpang tindih, adalah jika menghasilkan acak memiliki duplikat dalam milidetik yang sama.


9
1ms bisa menjadi waktu yang lama di beberapa sistem.
quant_dev

7
Ini sebenarnya tidak mengurangi kemungkinan tabrakan sama sekali. Probabilitas tabrakan setelah angka N persis sama dengan solusi asli OP. Trik menggunakan waktu saat ini sebagai seed biasanya digunakan ketika menetapkan kunci secara berurutan.
Cort Ammon

2
@Fresheyeball Saya yakin bahwa itu tidak berpengaruh, kecuali Random.makeInt () tidak benar-benar menghasilkan distribusi yang seragam dari nilai minimum integer ke nilai maksimum integer. Untuk setiap nilai lampau yang dihasilkan oleh fungsi ini, ada nilai acak dari makeInt yang, untuk langkah waktu yang tepat ini, menghasilkan nilai itu, menciptakan tabrakan. Karena semua nilai dari makeInt bisa digunakan, kemungkinan tumbukan persis sama dengan probabilitas tumbukan tanpa penambahan waktu.
Cort Ammon

2
@CortAmmon ini tidak menggunakan waktu saat ini sebagai benih , dan itu pasti membuat perbedaan selama angka N itu tidak semua dihasilkan selama milidetik yang sama, karena dua angka dengan bagian stempel waktu yang berbeda tidak pernah bertabrakan. Jika Anda membayangkan contoh jawaban lain dari satu paket per detik yang memiliki kemungkinan tabrakan 50% dalam waktu kurang dari satu hari, yang ini memiliki kemungkinan 0% tabrakan pada satu paket per detik, setidaknya hingga waktu yang currentTimeMillismembungkus.
hobbs

3
@ hobbs Anda lupa tentang integer overflow. Sekarang jika kunci OP yang digunakan adalah struktur yang mengandung 2 bilangan bulat, satu berisi System.currentTimeMillisdan satu berisi Random.makeInt(), maka kemungkinan tabrakan turun secara substansial. Namun, bukan itu yang dilakukan oleh kode dalam contoh ini. Mengingat setiap waktu sebelumnya dan nilai acak, dan setiap waktu saat ini, kemungkinan tabrakan identik dengan probabilitas dua angka acak bertabrakan di tempat pertama.
Cort Ammon

3

Itu tergantung pada probabilitas kegagalan dan konsekuensi dari kegagalan.

Saya ingat perdebatan antara orang-orang perangkat lunak dan perangkat keras di mana orang-orang perangkat keras menganggap bahwa algoritma dengan probabilitas kecil hasil yang salah (sekitar 1 kegagalan dalam 100 tahun) dapat diterima, dan orang-orang perangkat lunak berpikir ini adalah kutukan. Ternyata orang-orang perangkat keras secara rutin menghitung tingkat kegagalan yang diharapkan, dan sangat terbiasa dengan gagasan bahwa semuanya akan memberikan jawaban yang salah sesekali, misalnya karena gangguan yang disebabkan oleh sinar kosmik; mereka merasa aneh bahwa orang-orang perangkat lunak mengharapkan keandalan 100%.


1

Tentu, Anda memiliki probabilitas yang sangat rendah dari dua bilangan bulat 32-bit acak yang berurutan tetapi itu tidak sepenuhnya mustahil. Keputusan teknik yang tepat didasarkan pada apa konsekuensi dari tabrakan, perkiraan volume angka yang Anda hasilkan, masa hidup yang memerlukan keunikan & apa yang terjadi jika pengguna jahat mulai berusaha menyebabkan tabrakan.


0

Dapat diterima untuk berasumsi bahwa angka acak akan unik tetapi Anda harus berhati-hati.

Dengan asumsi nomor acak Anda didistribusikan secara merata, kemungkinan tabrakan kira-kira (n 2 /2) / k di mana n adalah jumlah angka acak Anda menghasilkan dan k adalah jumlah kemungkinan nilai-nilai "acak" nomor dapat mengambil.

Anda tidak menaruh angka pada kemungkinan astronomis jadi mari kita anggap sebagai 1 dalam 2 30 (kira-kira dalam satu miliar). Lebih jauh lagi katakanlah Anda menghasilkan 2 30 paket (jika setiap paket mewakili sekitar satu kilobyte data maka ini berarti sekitar satu terabyte dari total data, besar tetapi tidak terbayangkan). Kami menemukan kami membutuhkan nomor acak dengan setidaknya 2 89 nilai yang mungkin.

Pertama, angka acak Anda harus cukup besar. Angka acak 32 bit dapat memiliki paling banyak 2 32 nilai yang mungkin. Untuk server yang sibuk yang tidak cukup tinggi.

Kedua generator nomor acak Anda harus memiliki keadaan internal yang cukup besar. Jika pembangkit angka acak Anda hanya memiliki keadaan internal 32-bit maka tidak peduli seberapa besar nilai yang Anda hasilkan dari itu, Anda masih akan mendapatkan paling banyak 2 32 nilai yang mungkin.

Ketiga jika Anda membutuhkan nomor acak untuk menjadi unik di seluruh koneksi daripada hanya dalam koneksi, generator nomor acak Anda perlu diunggulkan dengan baik. Ini benar terutama jika program Anda sering dinyalakan ulang.

Secara umum generator nomor acak "reguler" dalam bahasa pemrograman tidak cocok untuk penggunaan tersebut. Generator angka acak yang disediakan oleh perpustakaan kriptografi umumnya.


0

dibangun ke dalam beberapa jawaban di atas adalah asumsi bahwa generator angka acak memang 'datar' - bahwa probabilitas setiap dua angka menjadi nomor berikutnya yang dihasilkan adalah sama.

Itu mungkin tidak benar untuk kebanyakan generator angka acak. Sebagian besar yang menggunakan polinomial orde tinggi berulang kali diterapkan pada biji.

Yang mengatakan, ada banyak sistem di luar sana yang bergantung pada skema ini, biasanya dengan UUID. Sebagai contoh, setiap objek dan aset dalam Second Life memiliki UUID 128 bit, dihasilkan secara acak, dan mereka jarang bertabrakan.


0

Banyak orang telah memberikan jawaban berkualitas tinggi, tetapi saya ingin menambahkan beberapa poin minor: pertama, poin @nomadictype tentang paradoks ulang tahun sangat baik .

Poin lain: keacakan tidak sesederhana untuk menghasilkan dan mendefinisikan sebagaimana orang mungkin menganggap. (Sebenarnya, sebenarnya ada tes statistik untuk keacakan tersedia).

Dengan mengatakan itu, penting untuk menyadari Kejatuhan Gambler , yang merupakan kekeliruan statistik di mana orang menganggap bahwa peristiwa independen entah bagaimana saling mempengaruhi. Peristiwa acak umumnya secara statistik independen satu sama lain - yaitu jika Anda secara acak menghasilkan "10", itu tidak mengubah probabilitas Anda di masa depan untuk menghasilkan lebih banyak "10". (Mungkin seseorang bisa membuat pengecualian untuk aturan itu, tapi saya berharap itu akan menjadi kasus untuk hampir semua generator bilangan acak).

Jadi jawaban saya adalah jika Anda dapat berasumsi bahwa urutan bilangan acak yang cukup lama adalah unik, mereka tidak akan benar-benar bilangan acak karena itu akan menjadi pola statistik yang jelas. Juga, itu akan menyiratkan bahwa setiap angka baru bukan peristiwa independen karena jika Anda menghasilkan, misalnya, angka 10 yang berarti bahwa probabilitas menghasilkan angka 10 di masa mendatang adalah 0% (tidak mungkin terjadi), ditambah itu berarti Anda akan meningkatkan peluang mendapatkan angka selain 10 (yaitu semakin banyak angka yang Anda hasilkan, semakin tinggi probabilitas masing-masing angka yang tersisa menjadi).

Satu hal lagi yang perlu dipertimbangkan: peluang memenangkan Powerball dari memainkan satu pertandingan adalah, seperti yang saya pahami, sekitar 1 banding 175 juta. Namun, peluang seseorang untuk menang jauh lebih tinggi dari itu. Anda lebih tertarik pada peluang seseorang "menang" (yaitu Menjadi duplikat) daripada dalam peluang nomor tertentu "menang" / menjadi duplikat.


Jika seseorang menghasilkan pengidentifikasi 4096-bit sedemikian rupa sehingga setiap bit kemungkinan sama-sama menjadi 0 atau 1 independen dari bit lain yang telah dihasilkan dalam pengidentifikasi yang sama atau yang lain, probabilitas bahwa dua pengidentifikasi akan cocok akan menjadi semakin kecil bahkan jika seseorang secara acak menghasilkan pengidentifikasi yang berbeda untuk masing-masing atom sekitar 4.0E81 di alam semesta yang dapat diamati. Fakta bahwa pengidentifikasi semacam itu hampir pasti unik tidak akan membuat mereka "non-acak"
supercat

@supercat Itu benar - mengingat jumlah yang cukup besar itu sangat tidak mungkin bahwa akan ada duplikat, tetapi itu bukan tidak mungkin. Ini benar-benar tergantung seberapa buruk konsekuensi dari ketidakunikan apakah OP menggambarkan itu ide yang baik.
EJoshuaS

Jika kemungkinan tabrakan kebetulan acak lebih kecil dari probabilitas serangan meteor yang melenyapkan perangkat yang mengandalkan id unik, dari perspektif teknik, tidak perlu khawatir tentang yang pertama. Akan ada kebutuhan besar untuk khawatir tentang apa pun yang dapat menyebabkan angka acak tidak independen, tetapi tabrakan acak akan menjadi masalah.
supercat

@supercat Saya pikir Anda salah membaca ini, lihat jawaban lain pada paradoks ulang tahun, saya pikir tabrakan jauh lebih mungkin daripada yang Anda hitung - OP hanya menggunakan nomor 32-bit jadi saya tidak yakin di mana Anda kembali mendapatkan 4096 dari, dan sebagai nomadictype menunjukkan kemungkinan tabrakan akhirnya dengan jumlah panjang yang sebenarnya sangat tinggi.
EJoshuaS

Anda benar bahwa angka 32-bit terlalu pendek bahkan untuk populasi kecil jika tabrakan benar-benar tidak dapat diterima. Jika seseorang menggunakan angka yang cukup besar, seseorang dapat mengurangi kemungkinan tabrakan acak ke titik di mana orang dapat dengan aman menganggap mereka Tidak Akan Terjadi, dan dalam banyak kasus menggunakan angka yang lebih besar mungkin lebih baik daripada mencoba menggunakan cara lain untuk memastikan keunikan, karena yang terakhir umumnya memerlukan memiliki akses ke keadaan transisi yang tidak dapat dibatalkan atau dibatalkan, bahkan jika jam sistem diatur ulang atau sistem dimuat ulang dari cadangan.
supercat

0

Tidak masalah berapa banyak bit yang Anda gunakan - Anda TIDAK BISA menjamin bahwa dua angka "acak" akan berbeda. Sebagai gantinya, saya sarankan Anda menggunakan sesuatu seperti alamat IP atau alamat jaringan lain dari komputer dan nomor urut, lebih disukai nomor urut BES HONKIN - 128 bit (jelas tanpa tanda) terdengar seperti awal yang baik, tetapi 256 akan lebih baik.


-1

Tidak, tentu saja tidak. Kecuali jika Anda menggunakan sampel tanpa penggantian, ada kemungkinan - betapapun kecil - duplikasi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.