16

Attualmente sto sviluppando un'applicazione per Archiviazione tabelle di Azure. In quell'applicazione ho una tabella che avrà relativamente pochi inserimenti (un paio di migliaia/giorno) e la chiave primaria di queste entità sarà usata in un'altra tabella, che avrà miliardi di righe.Incremento automatico su Archiviazione tabelle di Azure

Pertanto, sto cercando un modo per utilizzare un numero intero auto-incrementato, anziché GUID, come chiave primaria nella tabella piccola (dal momento che risparmierà molto spazio di archiviazione e scalabilità degli inserti non è davvero un problema).

Ci sono state alcune discussioni sull'argomento, ad es. http://social.msdn.microsoft.com/Forums/en/windowsazure/thread/6b7d1ece-301b-44f1-85ab-eeb274349797.

Tuttavia, poiché i problemi di concorrenza possono essere davvero difficili da eseguire il debug e individuare, mi sento un po 'a disagio nell'implementazione del problema. La mia domanda è quindi se c'è un'impegnazione ben collaudata di questo?

+0

Se siete veramente preoccupati, una tabella in SQL azzurro genera i valori di identità? – Andrew

+0

Questo è un buon suggerimento. Tuttavia questo mi costringerebbe a configurare il mio SQL-server, perché i servizi di dati SQL di Azure non supportano le colonne di identità: http://www.shanmcarthur.net/cloud-services/design-strategies-for-Azure-and-SDS . – Yrlec

risposta

4

non ho ancora implementato questo, ma sto lavorando su di esso ...

Si potrebbe seminare una coda con i tuoi prossimi ids da utilizzare, poi basta farli fuori la coda quando ne avete bisogno.

È necessario mantenere una tabella per contenere il valore del numero più grande aggiunto alla coda. Se sai che non utilizzerai una tonnellata di interi, potresti avere un lavoratore ogni tanto sveglio e assicurarti che la coda contenga ancora interi. Si potrebbe anche avere una coda int utilizzata che l'operatore potrebbe controllare per tenere d'occhio l'utilizzo.

Si potrebbe anche agganciare quell'operatore in modo che se la coda fosse vuota quando il codice aveva bisogno di un id (casualmente) potrebbe interrompere il pisolino del lavoratore per creare più chiavi al più presto.

Se la chiamata non riuscita si avrebbe bisogno di un modo per (dire al lavoratore che si sta per fare il lavoro per loro (blocco), quindi fare il lavoro dei lavoratori di ottenere il prossimo id e sbloccare)

  1. bloccare
  2. l'ultima chiave creata dal tavolo
  3. incremento e salvare
  4. sblocco

quindi utilizzare il nuovo valore.

+1

Ma come fa una coda a garantire che gli ID duplicati non vengano creati? Quello che posso capire da http://download.microsoft.com/download/5/2/D/52D36345-BB08-4518-A024-0AA24D47BD12/Windows%20Azure%20Queue%20-%20Dec%202008.docx è che un il messaggio viene nuovamente aggiunto alla coda se un processo di lavoro non riesce durante l'elaborazione del messaggio di coda. È quindi necessario rendere il lavoro sul ruolo di lavoratore idempotente. Se lo stesso messaggio (vale a dire lo stesso ID) viene utilizzato da due diversi ruoli di lavoratore, non vedo come si possa renderlo idempotente. – Yrlec

+2

Se hai solo 1 woker che crea l'id, allora i duplicati verrebbero messi in coda. Quando si estrae gli ID dalla coda, ottenere il messaggio, quindi eliminare il messaggio prima di utilizzare il contenuto del messaggio (id). Ciò dovrebbe garantire che nessun ID venga usato più di una volta. Sembra lo scenario peggiore, quindi potresti perdere una chiave, ma la tua unicità dovrebbe essere ancora buona. –

+0

La seconda frase sopra dovrebbe essere: "Se hai solo 1 woker che crea l'id, allora i dups non verrebbero messi in coda ..." –

3

Se hai davvero bisogno di evitare i guids, hai considerato l'utilizzo di qualcosa basato su data/ora e poi sfruttando le chiavi di partizione per ridurre al minimo il rischio di concorrenza.

La chiave di partizione potrebbe essere per utente, anno, mese, giorno, ora, ecc. E la chiave di riga potrebbe essere il resto del datetime in un intervallo di tempo abbastanza piccolo per controllare la concorrenza.

Ovviamente devi chiedertelo, al prezzo della data in Azure, se vale la pena sfidare tutto questo sforzo extra (supponendo che un Guid funzionerà).

4

La soluzione che ho trovato che impedisce ID duplicati e consente di auto-incremento è di

  1. lock (lease) a blob e lasciare che agiscono come una porta logica.

  2. Quindi leggere il valore.

  3. Scrivi il valore incrementato

  4. Rilasciare il contratto di locazione

  5. Usa il valore della tua app/tavolo

Poi, se il vostro ruolo lavoratore dovesse bloccarsi durante il processo, poi avresti solo un ID mancante nel tuo negozio. IMHO è meglio dei duplicati.

Ecco una code sample and more information su questo approccio da Steve Marx

10

Per tutti coloro che si troveranno in cerca, c'è una soluzione migliore. Minimal time for table lock is 15 seconds - è orribile. Non usarlo se si desidera creare una soluzione veramente scalabile. Usa Etag!

Creare un'entità nella tabella per ID (è possibile anche denominarlo come ID o qualsiasi altra cosa).

1) Leggilo.

2) Incremento.

3) InsertOrUpdate WITHETag specificato (dalla query di lettura).

se l'ultima operazione (InsertOrUpdate) ha esito positivo, è disponibile un nuovo ID univoco con incremento automatico. Se fallisce (eccezione con HttpStatusCode == 412), significa che qualche altro client lo ha cambiato. Quindi, ripetere nuovamente 1,2 e 3. Il tempo normale per Read+InsertOrUpdate è inferiore a 200 ms. La mia utilità di test with source on github.

+0

Ottima idea. – PilotBob

+0

che dire dell'utilizzo di EGT per garantire operazioni atomiche, leggere e incrementare? E 'un modo praticabile per farlo? https://docs.microsoft.com/en-gb/azure/storage/storage-table-design-guide#entity-group-transactions –

Problemi correlati