Riprova il metodo per generare codice univoco

1

In un'app, un utente può avviare la generazione di un codice alfanumerico a sei cifre (effettivamente eseguito tramite Web API). Il codice deve essere verificato su un database remoto per assicurarsi che sia univoco. Oltre alla diagnostica o alla registrazione, la tabella DB viene utilizzata solo dall'API Web e da un processo Web di Azure che elimina i codici scaduti.

Nei miei test, le collisioni si sono verificate in media solo una volta in ~ 24K volte con un massimo di 85K e un minimo di 170. È quest'ultima che mi riguarda. Sebbene la tabella venga svuotata giornalmente dei codici scaduti, a un certo punto ci sarà una collisione. Sebbene improbabile, potrebbe accadere con pochissimi record nella tabella.

Vale la pena notare che a causa dei requisiti esterni, il codice è limitato a sei caratteri da AEFGHJKLPQRSTUWXYZ123456789.

Una soluzione semplicistica sarebbe quella di continuare a generare la generazione / controllo fino alla creazione di un codice univoco. Con ogni probabilità, ciò significherebbe solo 1-2 iterazioni. Ma non c'è garanzia. E certamente non può funzionare senza impedimenti.

Il prossimo passo sarebbe mettere un limite - diciamo 5 tentativi - attraverso un semplice ciclo. Questo può essere abbastanza di una soluzione. Nonostante la preoccupazione che l'utente sarebbe frustrato se alla fine fallisce, se lo fa c'è probabilmente abbastanza sbagliato con il sistema generale per rovinare comunque l'esperienza dell'utente.

Ho un buon codice backoff esponenziale quindi, anche se questo non è un problema di rete (anche una preoccupazione), può aiutare a incorporarlo nello schema dei tentativi. In realtà, quella potrebbe essere una bella soluzione catch-all. Considerando 5 ritardi temporali crescenti nel tentativo di riprovare, ciò consentirebbe a entrambe le possibilità per il codice logico di superare le possibilità di una collisione e di mitigare l'introduzione di maggiore stress sulle risorse di rete.

Qualsiasi suggerimento / osservazione sarebbe apprezzato.

FYI, questo è il codice utilizzato per generare i codici:

    /// <summary>
/// Generates a randomized alphanumeric code
/// </summary>
/// <param name="strLength">e.g. 6 chars</param>
/// <param name="charSet">e.g. AEFGHJKLPQRSTUWXYZ123456789</param>
/// <returns>string of the specified length</returns>
public static string GenerateCode(int strLength, string charSet)
{
    var chars = charSet.ToCharArray();
    var data = new byte[1];
    var crypto = new RNGCryptoServiceProvider();
    crypto.GetNonZeroBytes(data);
    data = new byte[strLength];
    crypto.GetNonZeroBytes(data);
    var result = new StringBuilder(strLength);
    foreach (var b in data)
    {
        result.Append(chars[b % (chars.Length)]);
    }
    return result.ToString();
}
    
posta Stonetip 22.12.2014 - 17:39
fonte

2 risposte

3

Pensiamo ai tuoi diversi codici a sei cifre. È possibile generare (26 (per alpha) + 10 (per numerico)) ^ 6 = 2176782336 voci diverse. Passiamo ora al paradosso dei compleanni se hai già elementi sqrt (2176782336) = 46656 (36 ^ 3) nella tua lista, avrai il 50% di possibilità di trovare un duplicato per ogni nuovo tentativo. Poiché stai compilando l'elenco sul server, sarà più difficile per il cliente trovare un codice non utilizzato.

Se non raggiungerai 46656 elementi in un giorno, hai ottime probabilità di utilizzare fino a 4 tentativi. Ma se ti avvicini alla barriera 46K, dovrai aumentare il numero di tentativi. Se si desidera una minore probabilità di collisioni utilizzare più cifre o più caratteri 25 per lettere minuscole (omit l) e 24 (Ometti O e I) per lettere maiuscole e 10 per numeri questo aumenterà la barriera del 50 per cento a 205379 (59 ^ 3).

sul lato server sperimenterai il cosiddetto problema dei raccoglitori di coupon Analogamente al problema, i clienti cercano di darti dei coupon (il server) che non hai già ...

hth.

    
risposta data 22.12.2014 - 18:01
fonte
2

Puoi usare una tabella con un ID autoincrementante come base per il tuo codice. Se necessario, iniziare gli incrementi a 100.000 per 6 cifre. Inserisci una riga, ottieni l'ID e restituiscilo. Sarà garantito per essere unico.

A seconda dei livelli di utilizzo previsti, potresti prendere in considerazione l'aggiunta di alcune lettere casuali all'ID. Quindi il codice '1234' diventa '1234AB'. Ciò rende più difficile inciampare sui codici di altre persone.

Puoi anche implementare quanto sopra come tabella di ricerca. Riempi una tabella con i codici appropriati e restituisci quella corrispondente in base all'id auto incrementato.

    
risposta data 22.12.2014 - 18:31
fonte

Leggi altre domande sui tag