Простий доказ того, що GUID не унікальний [закритий]


323

Я хотів би довести, що GUID не є унікальним у простій тестовій програмі. Я очікував, що наступний код працюватиме годинами, але він не працює. Як я можу змусити його працювати?

BigInteger begin = new BigInteger((long)0);
BigInteger end = new BigInteger("340282366920938463463374607431768211456",10);  //2^128
for(begin; begin<end; begin++)
  Console.WriteLine(System.Guid.NewGuid().ToString());

Я використовую C #.


107
Як розробник програмного забезпечення, що б ви сказали, якби користувач прийшов до вас і сказав "це не працює"?
JoshJordan

152
Зачекайте кілька трильйонів років.
варення

67
Оновлений, тому що це найцікавіше, що я бачив сьогодні в Інтернеті.
jrockway

32
@jrockway - lol. Мені хвилюється знайти щось з цього питання, яке не є принципово неправильним. Чим довше я на це дивлюся, тим смішніше це стає.
tylerl

243
Це лише глобально унікально, тому унікальне лише на нашій планеті. Якщо ви хочете по-справжньому унікальний ідентифікатор, вам потрібно використовувати універсальний унікальний ідентифікатор (UUID). Я припускаю, що вас цікавить лише унікальність всередині нашого Всесвіту. :-)
tvanfosson

Відповіді:


407

Кай, я створив програму, яка буде робити те, що ти хочеш, використовуючи теми. Він ліцензований за такими умовами: ви повинні платити мені 0,0001 долара за годину за ядро ​​процесора, на якому ви працюєте. Плата сплачується в кінці кожного календарного місяця. Будь ласка, зв'яжіться зі мною, щоб дізнатись про мій рахунок Paypal якнайшвидше.

using System;
using System.Collections.Generic;
using System.Linq;

namespace GuidCollisionDetector
{
    class Program
    {
        static void Main(string[] args)
        {
            //var reserveSomeRam = new byte[1024 * 1024 * 100];     // This indeed has no effect.

            Console.WriteLine("{0:u} - Building a bigHeapOGuids.", DateTime.Now);
            // Fill up memory with guids.
            var bigHeapOGuids = new HashSet<Guid>();
            try
            {
                do
                {
                    bigHeapOGuids.Add(Guid.NewGuid());
                } while (true);
            }
            catch (OutOfMemoryException)
            {
                // Release the ram we allocated up front.
                // Actually, these are pointless too.
                //GC.KeepAlive(reserveSomeRam);
                //GC.Collect();
            }
            Console.WriteLine("{0:u} - Built bigHeapOGuids, contains {1} of them.", DateTime.Now, bigHeapOGuids.LongCount());


            // Spool up some threads to keep checking if there's a match.
            // Keep running until the heat death of the universe.
            for (long k = 0; k < Int64.MaxValue; k++)
            {
                for (long j = 0; j < Int64.MaxValue; j++)
                {
                    Console.WriteLine("{0:u} - Looking for collisions with {1} thread(s)....", DateTime.Now, Environment.ProcessorCount);
                    System.Threading.Tasks.Parallel.For(0, Int32.MaxValue, (i) =>
                    {
                        if (bigHeapOGuids.Contains(Guid.NewGuid()))
                            throw new ApplicationException("Guids collided! Oh my gosh!");
                    }
                    );
                    Console.WriteLine("{0:u} - That was another {1} attempts without a collision.", DateTime.Now, ((long)Int32.MaxValue) * Environment.ProcessorCount);
                }
            }
            Console.WriteLine("Umm... why hasn't the universe ended yet?");
        }
    }
}

PS: Я хотів випробувати бібліотеку розширень Parallel. Це було легко.

І використовувати OutOfMemoryException як контрольний потік просто не так.

EDIT

Що ж, схоже, це все ж привертає голоси. Тому я виправив проблему GC.KeepAlive (). І змінив його для запуску з C # 4.

І щоб уточнити мої умови підтримки: підтримка доступна лише 28 / лютого 2010 року. Будь ласка, використовуйте машину часу, щоб робити запити про підтримку лише в цей день.

EDIT 2 Як завжди, GC виконує кращу роботу, ніж я в управлінні пам'яттю; будь-які попередні спроби зробити це самостійно були приречені на провал.


120
Ця остання Console.WriteLine змусила мене сміятися по-справжньому. Я думаю, вам слід кинути CommonlyAcceptedCosmologicTheoriesWrongExceptionзамість цього.
Р. Мартіньо Фернандес

17
чи позначає це як Прийняте також означає, що @Kai приймає умови, передбачені @ligos?
кб.

3
Налаштування reserveSomeRam = null;насправді нічого не дає.
DevinB

4
@devinb, будь ласка, поясніть? схоже, це звільнення байтів, які раніше було виділено, так що GC може Collect()це зробити. Чому вона нічого не досягає?
mythz

3
GuidCollisionDetector. Назва має потенціал
Ufuk Hacıoğulları

226

Це триватиме набагато більше годин. Якщо припустити, що він циркулює на частоті 1 ГГц (що не буде - це буде набагато повільніше, ніж це), він працюватиме протягом 10790283070806014188970 років. Що приблизно в 83 мільярди разів довше, ніж вік Всесвіту.

Якщо припустити закон Мураса, було б набагато швидше не запускати цю програму, чекати кілька сотень років і запускати її на комп'ютері, який у мільярди разів швидше. Насправді будь-яка програма, яка запускає більше часу, ніж швидкість подвійного процесора, щоб подвоїтись (приблизно 18 місяців), завершиться швидше, якщо зачекати, поки швидкість процесора збільшиться, і придбати новий процесор перед його запуском (якщо ви не пишете його, щоб він може бути призупинено та відновлено на новому апаратному забезпеченні).


27
чорт, - тож, може, сервальні нитки, що генерують напрямні, є кращою ідеєю?
Кай

107
4 потоки на чотирьохядерному процесорі змусили б його працювати у 20 мільярдів разів у віці Всесвіту - так, так, це допомогло б дуже багато.
rjmunro

34
Я підозрюю, що це троль, але, навряд чи, це не так: нитки не магічні. Якщо ви можете зробити мільярд операцій в секунду на одній нитці, то перехід на десять потоків означає, що кожна працює на 1/10 так само часто. Кожна нитка робить 100 М операцій в секунду; загальна кількість операцій в секунду не збільшується. Спосіб збільшення кількості операцій в секунду - це придбання більшої кількості комп'ютерів. Припустимо, ви купили мільярд більше комп’ютерів. Це зменшило б проблему лише до 10790283070806 років, а це ще більше чотирьох годин.
Ерік Ліпперт

10
Я думаю, що rjmunro припускає, що кожна нитка буде працювати на окремому ядрі; 83 мільярди всесвітів / 4 ядра дійсно приблизно дорівнюють 20 мільярдам всесвітів. Час придбати акції Intel!
Dour High Arch

4
@Erik 83 мільярди процесорів означає, що ви зможете це зробити приблизно за те, скільки часу існувала Всесвіт. Так що навіть цього недостатньо.
rjmunro

170

GUID теоретично не унікальний. Ось ваш доказ:

  • GUID - це 128-бітове число
  • Ви не можете генерувати 2 ^ 128 + 1 або більше GUID без повторного використання старих GUID

Однак якби вся потужність сонця була спрямована на виконання цього завдання, вона замерзла б задовго до її закінчення.

GUID можуть бути створені за допомогою декількох різних тактик, деякі з яких вживають спеціальних заходів, щоб гарантувати, що дана машина не генерує той самий GUID двічі. Виявлення зіткнень у конкретному алгоритмі засвідчило б, що ваш конкретний метод генерування GUID поганий, але загалом не підтверджував би нічого про GUID.


44
Принцип «Голуби» на допомогу!
yfeldblum

22
+1 для коментаря, що холодним сонцем йде. Десь був цікавий коментар про безглуздість ключів шифрування> 256 біт. Для повторення всіх можливих ключових значень потрібно більше енергії, ніж уся Всесвіт. Трохи вправлятися в процесорі потрібно невелика кількість енергії (це те, що генерує тепло), що при множенні в 2 ^ 256 разів - це дійсно масове число, що перевищує енергію, що зберігається у Всесвіті, використовуючи E = mc2, Всесвіту знадобиться маса 2 ^ 227 кг, наше сонце 2 ^ 101 кг, так що 2 ^ 126 сонця!
Skizz

31
@Skizz: Це стосується лише грубої атаки. Коли схема шифрування "зламана", це означає, що її можна вирішити за менший час, ніж груба сила, але час вирішення залишається пропорційним розміру ключа.
Стівен Судіт

1
@StevenSudit: пропорційний показник розміру ключа (якщо P == NP)
Ihar Bury

1
@Orlangur Пропорційний розміру ключа, виміряному в бітах.
Стівен Судіт

137

Звичайно, GUID можуть стикатися. Оскільки GUID є 128-бітними, просто генеруйте 2^128 + 1їх і за принципом голубого отвору має відбутися зіткнення.

Але коли ми говоримо, що GUID є унікальним, то, що ми насправді маємо на увазі, що простір ключів настільки великий, що практично неможливо випадково генерувати той самий GUID двічі (якщо припустити, що ми генеруємо GUIDs випадковим чином).

Якщо ви генеруєте послідовність nGUIDs випадковим чином, то ймовірність принаймні одного зіткнення приблизно p(n) = 1 - exp(-n^2 / 2 * 2^128)(це проблема з днем народження з кількістю можливих днів народження 2^128).

   n     p(n)
2^30 1.69e-21
2^40 1.77e-15
2^50 1.86e-10
2^60 1.95e-03

Для того, щоб ці цифри бетону, 2^60 = 1.15e+18. Отже, якщо ви генеруєте один мільярд GUID в секунду, вам знадобиться 36 років, щоб генерувати 2^60випадкові GUID, і навіть тоді ймовірність виникнення зіткнення все ще залишається 1.95e-03. Ви, швидше за все, будете вбиті в якийсь момент свого життя ( 4.76e-03), ніж ви зіткнетесь протягом наступних 36 років. Удачі.


239
Якщо вас вбили в якийсь момент вашого життя, шанси, що це буде наприкінці.
Майкл Майєрс

25
@mmyers: Відмінний момент. Це означає, що зараз мої шанси на вбивство є абсурдно низькими, оскільки це ще не кінець мого життя. О, зачекайте ...
Стівен Судіт

Крім того, якщо за короткий період часу буде створено два GUID, шанси їх використання в одній системі незначні. Тому це збільшує унікальність.
AMissico

Ці цифри та посилання на проблему з днем ​​народження безглузді. Алгоритми генерації GUID не генерують значення у всьому діапазоні з однаковою ймовірністю. Насправді IIRC оригінальний алгоритм використовував MAC-адресу генеруючого ПК + поточний час як частину результату - що знижує ризик зіткнення з Посібниками, сформованими на інших ПК, але, звичайно, зменшує простір ключів.
Джо

17
Ви припускаєте, що ймовірність вбивства є постійною для всіх людей. Але, очевидно, люди, які пишуть зауваження до чиновників у дописах на форумі, - це тип людей, які швидше за все будуть вбиті, ніж звичайна людина.
Джей

61

Якщо ви переживаєте за унікальність, ви завжди можете придбати нові GUID, щоб ви могли викинути старі. Я покладу трохи на eBay, якщо хочете.


13
Класно - скільки за весь набір, від 0 до (2 ^ 128) -1?
Steve314

23
У продажу - 0,01 дол. США за 1 тис. GUID. Я закину бамбукові вітрові куранти, якщо ви замовляєте протягом наступних 60 хвилин.
ctacke

7
Мій набір більш ексклюзивний та більш високої якості. Вони перевіряються та перевіряються, що робить їх вартістю 1 долара за GUID. Ви навіть можете придбати їх партіями, якщо ви не хочете робити цілі інвестиції за один раз. Мені доведеться стягувати додаткові 10 доларів за партію.
Томас

3
Я налаштую вас на щомісячний план і дам вам необмежені орієнтири на правильну ціну. ^ Ці хлопці намагаються обманути вас і продати вам завищені путівники. Я продам вам якісні посібники, виготовлені в Китаї!
ErocM

47

Особисто я вважаю, що "великий вибух" стався, коли зіткнулися два GUID.


4
Пам'ятайте. Для цього потрібен "особливий" програміст ...
AnthonyLambert

Я хотів би почути ваші міркування до вашої теорії. Я думаю, що ми могли б почати нову релігію, засновану на цьому, і набрати T.Cruise!
ErocM

@ErocM; Див. "Космологія Брана" ( en.wikipedia.org/wiki/Brane_cosmology ) та "Мембрана (М-теорія)" ( en.wikipedia.org/wiki/Membrane_(M-Theory) ). Ідея полягає в тому, якщо дві брани торкаються нового Всесвіту. Отже, ви можете зробити висновок, що якщо два GUID торкаються, таким чином створюється новий Всесвіт.
AMissico

2
Якщо Timecop навчив нас чомусь, те саме, що ця речовина не може займати той самий простір в будь-який момент часу Отже, якщо два GUID, де зіткнутися, вони поглинають один одного, і внаслідок цього приплив призведе до появи чорної діри, поглинаючи весь Всесвіт. Тож насправді це не створить Всесвіт, воно знищить його.
AJC

42

Можна показати, що в O (1) час із варіантом квантового алгоритму богосорту .

Guid g1 = Guid.NewGuid();
Guid g2 = Guid.NewGuid();
if(g1 != g2) Universe.Current.Destroy();

21
Я отримую виняток, коли телефоную Destroy (). Виходячи з тексту, я думаю, що моєму комп’ютеру не вистачає необхідного обладнання для знищення поточного Всесвіту. Чи знаєте ви, де я міг би її отримати?
Стівен Судіт

11
@Steven: Ні, деякі хлопці з менеджменту надто переймалися тим, наскільки погано цей API буде виглядати для громадськості, і продиктували це, щоб він завжди провалювався з "міркувань безпеки". Якщо подивитися на початку методу є тільки що одна рядки: throw new MundaneHardwareException();. У будь-якому разі, я чув, що хлопці в ЦЕРН мають якусь велику Адрон Thingy, яка могла б зробити трюк ...
R. Martinho Fernandes

7
@Martinho: Ага, добре. Я розгляну заміну Universe.Current.Destroy()на Cern.Lhc.DestroyThisUniverse().
Стівен Судіт

61
Я знав, що є причина, яку я запрограмував у Haskell. Ці побічні ефекти стають страшнішими.
Едвард КМЕТТ

6
"Існує теорія, яка стверджує, що якщо хто-небудь коли-небудь відкриє для чого саме Всесвіт і чому він є тут, він миттєво зникне і заміниться чимось ще більш дивно незрозумілим. Є ще одна теорія, яка стверджує, що це вже відбулося . " - Дуглас Адамс, Путівник автостопом по Галактиці
Майк Пірнат

28

Будь-які два GUID дуже ймовірно унікальні (не рівні).

Дивіться цей запис SO та з Вікіпедії

Незважаючи на те, що кожен створений GUID не гарантовано є унікальним, загальна кількість унікальних ключів (2 ^ 128 або 3,4 × 10 ^ 38) настільки велика, що ймовірність створення одного і того ж числа двічі дуже мала. Наприклад, розглянемо спостережуваний Всесвіт, який містить близько 5 × 10 ^ 22 зірок; кожна зірка може тоді мати 6,8 × 10 ^ 15 універсальних унікальних GUID.

Тож, напевно, вам доведеться чекати ще багато мільярдів років, і сподіваєтесь, що ви потрапили до всесвіту, як ми знаємо, що він закінчується.


так що 2 ^ 128 не є правильною кількістю можливих посібників?
Кай

21
Це є. Чому, на вашу думку, 2 ^ 128 - це невелика кількість?
jrockway

Так, 2 ^ 128 - правильна кількість можливих настанов.
Гравітон

3
Це пекло числа. $ irb >> 2**128 => 340282366920938463463374607431768211456
adamJLev

45
@ Infinity - Навіть тобі?
Остін Річардсон

27

[Оновлення:] Як вказують коментарі нижче, новіші GUID MS - це V4 і не використовують MAC-адресу як частину генерації GUID (я не бачив жодних ознак реалізації V5 від MS, хоча, якщо хтось має посилання, що підтверджує це, повідомте мене). Хоча WIth V4, час все ще є фактором, і шанси на дублювання GUID залишаються такими невеликими, що не мають значення для будь-якого практичного використання. Ви, звичайно, ніколи не зможете генерувати повторюваний GUID лише з одного єдиного тесту на систему, як це намагався зробити ОП.

Більшість із цих відповідей не містить важливого моменту щодо впровадження GUID Microsoft. Перша частина GUID заснована на часовій марці, а інша - на MAC-адресі мережевої карти (або випадковому номері, якщо не встановлено NIC).

Якщо я правильно це розумію, це означає, що єдиним надійним способом дублювання GUID було б запуск одночасних поколінь GUID на декількох машинах, де MAC-адреси були однаковими І де годинники в обох системах були в той самий точний час, коли генерація трапляється (часова мітка заснована на мілісекундах, якщо я правильно це розумію) .... навіть тоді є безліч інших бітів у кількості, які є випадковими, тому шанси все ще малі.

Для всіх практичних цілей GUID є універсальними.

На блозі "The Old New Thing" є досить хороший опис MS GUID


3
Це фактично можливо при використанні віртуалізації. Ви можете і отримуєте копії посібників.
Горан

8
Раймонд застарів у частині MAC-адреси, хоча Microsoft вже не використовує їх. Дивіться en.wikipedia.org/wiki/GUID#Algorithm щодо різниці між V1 та V4 Guidi.
Майкл Стум

1
Це вже не так. Поточна схема V5 - це лише 128 біт чистої псевдовипадкової користі.
Едвард КМЕТТ

смішно, як ви констатуєте все, що я зробив на місяць пізніше мене, і ви отримуєте 16 балів, а у мене ще 0?
AnthonyLambert

1
Я Тоні, з цим є щось дивне. Коли я відповів на повідомлення, було лише 3 чи 4 відповіді, і я не пам’ятав, щоб бачив твою ... якби я був, я б просто відмовив. Зазвичай я не відповідаю на питання, коли вже є інші відповіді, які досить добре висвітлюють це питання (саме тому, мабуть, у мене досить низький загальний представник).
Стівен М. Редд

23

Ось чудовий маленький метод розширення, який ви можете використовувати, якщо хочете перевірити унікальність орієнтирів у багатьох місцях свого коду.

internal static class GuidExt
{
    public static bool IsUnique(this Guid guid)
    {
        while (guid != Guid.NewGuid())
        { }
        return false;
    }
}

Щоб зателефонувати, просто зателефонуйте Guid.IsUnique, коли ви створюєте нове керівництво ...

Guid g = Guid.NewGuid();
if (!g.IsUnique())
{
    throw new GuidIsNotUniqueException();
}

... чорт, я навіть порекомендував би зателефонувати двічі, щоб переконатися, що він зрозумів правильно в першому раунді.


2
Як це забезпечує те, що this guidніколи в цьому світі не було створено? : p Heck нам потрібен світовий пул путівників. :)
nawfal

19

Розрахунок до 2 ^ 128 - амбітний.

Давайте уявимо, що ми можемо налічувати 2 ^ 32 ідентифікатори в секунду на машину - не таке амбітне, оскільки це навіть не 4,3 мільярда в секунду. Дозволяє виділити 2 ^ 32 машини для цього завдання. Крім того, давайте отримаємо від 2 до 32 цивілізацій, щоб кожна відводила однакові ресурси для цього завдання.

Поки ми можемо порахувати 2 ^ 96 ідентифікаторів в секунду, тобто ми будемо рахувати 2 ^ 32 секунди (трохи більше 136 років).

Тепер все, що нам потрібно, - це отримати 4 294 967 296 цивілізацій, щоб кожен присвятив 4 294 967 296 машинам, кожна машина здатна нарахувати 4 294 967 296 ідентифікаторів в секунду, суто для цього завдання протягом наступних 136 років - я пропоную розпочати цю важливу задачу вже зараз; -)


17

Добре, якщо час роботи 83 мільярди років вас не лякає, подумайте, що вам також потрібно буде десь зберігати створені GUID, щоб перевірити, чи є у вас дублікат; для зберігання 2 ^ 128 16-байтних номерів потрібно буде лише виділити 4951760157141521099596496896 терабайт оперативної пам’яті вперед, тому уявляючи, що у вас є комп'ютер, який міг би вмістити все це, і що ви хочете якось знайти місце для придбання терабайтних DIMM по 10 грамів кожен, разом вони важать більше 8 мас Землі, тому ви можете серйозно змістити її з поточної орбіти, перш ніж навіть натиснути «Виконати». Подумай двічі!


12
for(begin; begin<end; begin)
    Console.WriteLine(System.Guid.NewGuid().ToString());

Ви не збільшуєтесь, beginтому умова begin < endзавжди справжня.


1
ні - тому що я не можу повторити bigint
Кай

3
Чи насправді це важливо, якщо він циклічно вічно проти петлі 340282366920938463463374607431768211456 разів?
Джей

3
так що ... ви б краще пробивали 340282366920938463463374607431768211456 разів або назавжди!?!?!?
ErocM

насправді це те, що реально відповідає на питання! і голосів взагалі немає: p
nawfal


9

Імовірно, у вас є підстави вважати, що алгоритм створення посібників не генерує справді випадкових чисел, а насправді веде цикл з періодом << 2 ^ 128.

наприклад RFC4122 метод, який використовується для отримання GUID, який фіксує значення деяких бітів.

Докази їзди на велосипеді залежатимуть від можливого розміру періоду.

Для невеликих періодів хеш-таблиця хеша (GUID) -> GUID із заміною при зіткненні, якщо GUID не збігаються (припиняються, якщо вони є), може бути підходом. Розглянемо також лише заміну випадкової частки часу.

Зрештою, якщо максимальний період між зіткненнями достатньо великий (і не відомий заздалегідь), будь-який метод збирається створити ймовірність того, що зіткнення було б знайдено, якби воно існувало.

Зауважте, що якщо метод генерації Guids заснований на тактовій частоті (див. RFC), то, можливо, неможливо визначити, чи існують зіткнення, оскільки (а) ви не зможете чекати досить довго, щоб годинник обернувся, або (b) ви не можете вимагати достатньої кількості Посібників протягом цілодобової галочки, щоб змусити зіткнутись.

Крім того, ви можете показати статистичну залежність між бітами в Посібнику або співвідношення бітів між Guids. Такий взаємозв'язок може зробити дуже імовірним, що алгоритм є помилковим, не маючи необхідності знайти фактичне зіткнення.

Звичайно, якщо ви просто хочете довести, що Guids може зіткнутися, відповідь - це математичний доказ, а не програма.


8

Я не розумію, чому ніхто не згадав про модернізацію вашої відеокарти ... Безумовно, якщо у вас є висококласний NVIDIA Quadro FX 4800 або щось подібне (192 CUDA ядра), це пішло б швидше ...

Звичайно, якби ви могли дозволити собі декілька NVIDIA Qadro Plex 2200 S4 (при 960 ядрах CUDA кожен), цей розрахунок справді кричить. Можливо, NVIDIA буде готовий позичити вам декілька на «Демонстрацію технологій» як піару?

Звичайно, вони хотіли б стати частиною цього історичного розрахунку ...


хммм ..... Я міг би запустити його на нашій 10000 сітці вузлів на роботі.
AnthonyLambert

8

Але чи маєте ви бути впевнені, що у вас є дублікат, чи вас хвилює лише те, чи може бути дублікат. Щоб бути впевненим, що у вас двоє людей з одним і тим же днем ​​народження, вам потрібно 366 осіб (не рахуючи високосного року). Щоб мати більше, ніж 50% шансів мати двох людей з одним і тим же днем ​​народження, вам потрібно всього 23 людини. Ось проблема з днем народження .

Якщо у вас є 32 біти, вам потрібно лише 77 163 значення, щоб мати більше, ніж 50% шансу на отримання дубліката. Спробуй:

Random baseRandom = new Random(0);

int DuplicateIntegerTest(int interations)
{
    Random r = new Random(baseRandom.Next());
    int[] ints = new int[interations];
    for (int i = 0; i < ints.Length; i++)
    {
        ints[i] = r.Next();
    }
    Array.Sort(ints);
    for (int i = 1; i < ints.Length; i++)
    {
        if (ints[i] == ints[i - 1])
            return 1;
    }
    return 0;
}

void DoTest()
{
    baseRandom = new Random(0);
    int count = 0;
    int duplicates = 0;
    for (int i = 0; i < 1000; i++)
    {
        count++;
        duplicates += DuplicateIntegerTest(77163);
    }
    Console.WriteLine("{0} iterations had {1} with duplicates", count, duplicates);
}

1000 iterations had 737 with duplicates

Зараз 128 біт - це багато, тому ви все ще говорите про велику кількість предметів, що все ще дає низький шанс зіткнення. Вам знадобиться наступна кількість записів для заданих коефіцієнтів за допомогою наближення:

  • 0,8 мільярда мільярдів за 1/1000 шансів виникнення зіткнення
  • 21,7 мільярда мільярдів за 50% шансів статися до зіткнення
  • 39,6 мільярда мільярдів за 90% шансів виникнення зіткнення

Щорічно надсилається близько 1E14 електронних листів, тому на цьому рівні було б близько 400 000 років, перш ніж у вас буде 90% шансів мати двоє з тим самим GUID, але це набагато інше, ніж сказати, що вам потрібно запустити комп'ютер 83 мільярди разів вік Всесвіту або що Сонце холоне, перш ніж знайти дублікат.


7

Чи не всі ви пропускаєте головного моменту?

Я вважав, що GUID створюються за допомогою двох речей, які роблять шанси на те, що вони будуть глобально унікальними, досить високими. Одне - вони засіяні MAC-адресою машини, на якій ви знаходитесь, і два вони використовують час, який вони були створені, плюс випадкове число.

Тож якщо ви не запустите його на фактичній машині і не запустите всі здогадки протягом найменшого часу, який машина використовує для представлення часу в GUID, ви ніколи не будете генерувати те саме число, незалежно від того, скільки здогадок ви взяли за допомогою системного виклику.

Я думаю, якщо ви знаєте, як саме складається GUID, це фактично скоротить час на здогадки.

Тоні


3
Не всі GUID створені таким чином. Навіть якщо вони були, Каю потрібно лише дочекатися, поки мітка часу, що використовується для створення обгортки GUID, достатньо разів, для того, щоб він знову використовувався для створення GUID.
Dour High Arch

3
Посібники не базуються на mac-адресі з 2000 або 2001 року. Щодо одного з пакетів послуг для NT4 та / або Win2k, вони повністю змінили алгоритм. Тепер вони генеруються генератором випадкових чисел, мінус декількома бітами, які визначають, що це за напрям.
КрістоферА

4
не всі GUID походять з платформ Windows ...
AnthonyLambert

ОП згадує C #, тому це Windows. Крім того, чи GUID V4 - це лише річ для Windows?
Стівен Судіт

5
@Martinho: Так, але модульний тест Mono для Guid в GuidTest.cs містить метод, який створює два нових GUID і перевіряє їх на рівність, якщо вони не є рівними. Оскільки Mono будує успішно, ми можемо бути абсолютно впевнені, що його GUID-файли унікальні! :-)
Стівен Судіт

6

Ви можете зафіксувати GUID. Таким чином, ви повинні отримати результат набагато швидше.

Ну, звичайно, запуск декількох потоків одночасно - також гарна ідея, таким чином ви збільшите шанс на стан перегонів, генеруючи той самий GUID двічі в різних потоках.


6

GUID - це 124 біти, оскільки 4 біти містять номер версії.


Причина не додавати це як коментар: ніхто не згадав про це, і я не знаю, кому мені це сказати. :)
Behrooz

Hooooraaaay я зробив це. У якомусь "справжньому" додатку, про який я писав, у мене зіткнувся Керівник в таблиці з ~ 260k рядками. (MSSQL 2008 R2 Express).
Бехроз

6
  1. Відвідайте лабораторію кріогеніки в Нью-Йорку.
  2. Заморозити себе (приблизно) 1990 років.
  3. Знайдіть роботу в Planet Express.
  4. Купіть абсолютно новий процесор. Створіть комп’ютер, запустіть програму та поставте її в безпечне місце за допомогою псевдо-вічної машини для руху, як машина судного дня.
  5. Зачекайте, поки винайдеться машина часу.
  6. Перейти в майбутнє за допомогою машини часу. Якщо ви купили 128-бітовий процесор частотою 1 ГГц, перейдіть 3,938,453,320 days 20 hours 15 minutes 38 seconds 463 ms 463 μs 374 ns 607 psдо запуску програми.
  7. ...?
  8. ПРИБУТ !!!

... Це займає щонайменше 10,783,127років, навіть якщо у вас був процесор 1YHz, який в рази 1,000,000,000,000,000(або 1,125,899,906,842,624якщо ви вважаєте за краще використовувати двійковий префікс) в рази швидше, ніж процесор 1 ГГц.

Тому замість того, щоб чекати завершення обчислення, було б краще годувати голубів, які втратили своє житло, бо інші nголуби взяли їх додому. :(

Або ви можете зачекати, поки не буде винайдено 128-бітний квантовий комп'ютер. Тоді ви можете довести, що GUID не унікальний, використовуючи вашу програму в розумний час (можливо).


У цій відповіді я чекав посилання на супер героя - невдача за плакатом: p - все ж таки приголомшливий.
IbrarMumtaz

4

Ви пробували begin = begin + new BigInteger((long)1)замість початку ++?


2
ніхто не проголосував за відповідь, яка справді відповідає на питання: P
nawfal

4

Якщо кількість генерованих UUID відповідає закону Мура, враження про те, що ніколи не закінчуватиметься GUID в осяжному майбутньому, помилкове.

З 2 ^ 128 UUID, це займе лише 18 місяців * Log2 (2 ^ 128) ~ = 192 роки, перш ніж ми закінчимося з усіх UUID.

І я вірю (не маючи статистичних доказів того, що коли-небудь) за останні кілька років після масового прийняття UUID, швидкість, яку ми генеруємо UUID, зростає набагато швидше, ніж диктує закон Мура. Іншими словами, у нас, ймовірно, менше 192 років, поки нам не доведеться боротися з кризою UUID, це набагато швидше, ніж кінець Всесвіту.

Але оскільки ми точно не будемо їх виконувати до кінця 2012 року, ми залишимо це іншим видам для турботи про проблему.


3

Шанси помилки в коді, що генерує GUID, значно вищі, ніж шанси алгоритму, що генерує зіткнення. Шанси помилки у вашому коді для тестування GUID ще більше. Здаватися.


2

Програма, хоча і є її помилками, показує доказ того, що GUID не є унікальним. Ті, хто намагається довести протилежне, не мають сенсу. Це твердження лише підтверджує слабку реалізацію деяких варіацій GUID.

GUID не є унікальним за визначенням, він дуже унікальний за визначенням. Ви просто високо уточнили значення. Залежно від версії, реалізатора (MS чи інших), використання VM тощо, ваше визначення сильно змінюється. (див. посилання в попередньому дописі)

Ви можете скоротити свою 128-бітну таблицю, щоб довести свою думку. Найкращим рішенням є використання хеш-формули для скорочення таблиці з дублікатами, а потім використання повного значення, коли хеш стикається, і на основі цього знову генерувати GUID. Якщо ви працюєте з різних місць, ви зберігатимете свої хеш / повні ключі в центральному місці.

Пс: Якщо мета полягає лише в тому, щоб генерувати кількість x різних значень, створіть хеш-таблицю такої ширини і просто перевірте хеш-значення.


2

Не п ** я на багаття тут, але це насправді трапляється, і так, я розумію, що жарт ви давали цьому хлопцю, але GUID унікальний лише в принципі, я наткнувся на цю тему, тому що є помилка в емуляторі WP7, що означає, що кожного разу, коли він завантажується, він видає SAME GUID при першому його виклику! Отже, якщо теоретично у вас не може виникнути конфлікт, якщо виникає проблема із створенням вказаного GUI, тоді ви можете отримати дублікати

http://forums.create.msdn.com/forums/p/92086/597310.aspx#597310


1

Оскільки частина генерації Guid заснована на поточному часі машини, моя теорія отримання дубліката Guid така:

  1. Виконайте чисту установку Windows
  2. Створіть сценарій запуску, який скидає час до 2010-01-01 12:00:00 так само, як Windows завантажується.
  3. Одразу після сценарію запуску він запускає вашу програму для створення Guid.
  4. Клоніруйте цю інсталяцію Windows, щоб ви виключали будь-які тонкі відмінності, які можуть виникнути при наступних завантаженнях.
  5. Повторно зображте жорсткий диск із цим зображенням та завантажте машину кілька разів.

0

Для мене .. час, необхідний для створення одного ядра для створення UUIDv1, гарантує, що він буде унікальним. Навіть у багатоядерній ситуації, якщо генератор UUID дозволяє одночасно генерувати лише один UUID для вашого конкретного ресурсу (майте на увазі, що декілька ресурсів можуть повністю використовувати ті самі UUID, однак малоймовірно, оскільки ресурс є частиною адреси), то ви буде мати більше ніж достатньо UUID, щоб прослужити вас, поки часова мітка не вигорить. У цей момент я дійсно сумніваюся, що ви потурбуєтесь.


0

Ось також рішення:

int main()
{
  QUuid uuid;
  while ( (uuid = QUuid::createUuid()) != QUuid::createUuid() ) { }
  std::cout << "Aha! I've found one! " << qPrintable( uuid.toString() ) << std::endl;
}

Примітка: потрібен Qt, але я гарантую, що якщо ви дозволите йому працювати досить довго, він може знайти його.

(Зверніть увагу: насправді, тепер, коли я дивлюся на це, може бути щось щодо алгоритму генерації, що перешкоджає зіткненню двох згодом ууїдів, але я в цьому сумніваюся).


0

Єдиним рішенням довести, що GUID не є унікальним, було б мати світовий пул GUID. Кожен раз, коли десь генерується GUID, він повинен реєструватися в організації. Або чорт, ми можемо включити стандартизацію, що всім генераторам GUID потрібно зареєструвати її автоматично і для цього потрібно активне підключення до Інтернету!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.