Guid.NewGuid() VS un generatore di stringhe casuali da Random.Next()

Guid.NewGuid() VS un generatore di stringhe casuali da Random.Next()

Innanzitutto, come altri hanno notato, Random non è thread-safe; il suo utilizzo da più thread può causare la corruzione delle sue strutture dati interne in modo che produca sempre la stessa sequenza.

Secondo, Random è seminato in base all'ora corrente. Due istanze di Random creato nello stesso millisecondo (ricorda che un millisecondo è diversi milioni cicli del processore su hardware moderno) avranno lo stesso seme e quindi produrranno la stessa sequenza.

Terzo, ho mentito. Random non è seminato in base all'ora corrente; viene eseguito il seeding in base alla quantità di tempo in cui la macchina è stata attiva . Il seme è un numero a 32 bit e poiché la granularità è in millisecondi, mancano solo poche settimane prima che si avvolga. Ma non è questo il problema; il problema è:il periodo di tempo in cui crei quell'istanza di Random molto probabilmente entro pochi minuti dall'avvio della macchina. Ogni volta che spegni e riaccendi una macchina, o metti online una nuova macchina in un cluster, c'è una piccola finestra in cui vengono create istanze di Random e più succede, maggiori sono le probabilità che tu ottenga un seme che avevi prima.

(AGGIORNAMENTO:le versioni più recenti del framework .NET hanno mitigato alcuni di questi problemi; in quelle versioni non hai più ogni Random creati nello stesso millisecondo hanno lo stesso seme. Tuttavia ci sono ancora molti problemi con Random; ricorda sempre che è solo pseudo-casuale, non casuale di cripto-forza. Random è in realtà molto prevedibile, quindi se fai affidamento sull'imprevedibilità, non è adatto.)

Come altri hanno già detto:se vuoi una chiave primaria per il tuo database, fai generare al database una chiave primaria; lascia che il database faccia il suo lavoro. Se desideri un identificatore univoco globale, usa un guid; ecco a cosa servono.

E infine, se sei interessato a saperne di più sugli usi e gli abusi delle guide, allora potresti voler leggere la mia serie di "guide guida"; la prima parte è qui:

http://blogs.msdn.com/b/ericlippert/archive/2012/04/24/guid-guide-part-one.aspx


Come scritto in altre risposte, la mia implementazione ha avuto alcuni gravi problemi:

  • Sicurezza del filo: Casuale non è thread-safe.
  • Prevedibilità: il metodo non può essere utilizzato per identificatori critici per la sicurezza come i token di sessione a causa della natura della classe Random.
  • Collisioni: Anche se il metodo ha creato 20 numeri "casuali", la probabilità di una collisione non è (number of possible chars)^20 a causa del valore del seme di soli 31 bit e proveniente da una cattiva fonte. Dato lo stesso seme, qualsiasi la lunghezza della sequenza sarà la stessa.

Guid.NewGuid() andrebbe bene, tranne per il fatto che non vogliamo utilizzare brutti GUID negli URL e .NETs L'algoritmo NewGuid() non è noto per essere crittograficamente sicuro per l'uso nei token di sessione:potrebbe fornire risultati prevedibili se si conoscono poche informazioni.

Ecco il codice che stiamo usando ora, è sicuro, flessibile e per quanto ne so è molto improbabile che crei collisioni se viene data una lunghezza e una scelta di caratteri sufficienti:

class RandomStringGenerator
{
    RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
    public string GetRandomString(int length, params char[] chars)
    {
        string s = "";
        for (int i = 0; i < length; i++)
        {
            byte[] intBytes = new byte[4];
            rand.GetBytes(intBytes);
            uint randomInt = BitConverter.ToUInt32(intBytes, 0);
            s += chars[randomInt % chars.Length];
        }
        return s;
    }
}

"Generazione automatica di ID utente e ID post per l'identificazione nel database"... perché non utilizzare una sequenza o un'identità del database per generare le chiavi?

Per me la tua domanda è davvero:"Qual è il modo migliore per generare una chiave primaria nel mio database?" In tal caso, dovresti utilizzare lo strumento convenzionale del database che sarà una sequenza o un'identità. Questi hanno vantaggi rispetto alle stringhe generate.

  1. Sequenze/indice di identità migliore. Esistono numerosi articoli e post di blog che spiegano perché i GUID e così via creano indici scadenti.
  2. Sono garantiti per essere unici all'interno della tabella
  3. Possono essere generati in modo sicuro da inserimenti simultanei senza collisioni
  4. Sono semplici da implementare

Immagino che la mia prossima domanda sia:quali ragioni stai considerando i GUID o le stringhe generate? Integrerai tra database distribuiti? In caso contrario, dovresti chiederti se stai risolvendo un problema che non esiste.