Come gestire le richieste parallele, i diversi tempi di risposta e l'atomicità delle transazioni

1

Ho una tabella di dati e posso creare, aggiornare ed eliminare righe. Ho le API per fare queste operazioni. I seguenti passaggi si verificano

  1. Creo una riga e invio una richiesta di creazione al server.
  2. Aggiorno alcuni valori nella riga e invio una richiesta di aggiornamento prima che la risposta di create sia arrivata.
  3. Nel server poiché la riga di creazione non è stata completata, l'aggiornamento non può continuare.

Come gestisco questa situazione? Devo fare una richiesta di aggiornamento solo dopo il successo della creazione? Devo accodare la richiesta sul server?

Se la creazione fallisce, dovrei rimuovere le righe sul client? o dovrei ritentare la richiesta? Hai bisogno di aiuto su come affrontare questo. Grazie

    
posta Syed Suhail Ahmed 21.12.2017 - 13:45
fonte

3 risposte

2

Bene, le soluzioni più semplici consisterebbero nell'eseguire le operazioni sul lato client, aspettando la restituzione della creazione prima di inviare l'aggiornamento, oppure inviare entrambe le operazioni in un unico comando in modo che possano essere sequenziate sul lato server.

È difficile consigliare un approccio specifico perché non ci hai detto molto sui tuoi requisiti, ovvero hai requisiti di prestazione che non sono soddisfatti se aspetti la risposta alla creazione prima di inviare l'aggiornamento?

If the create fails, should I remove the rows on client? or should I retry the request?

Anche in questo caso dipende dalle tue esigenze e dal motivo dell'errore. Se l'errore era dovuto a un timeout di rete, riprovare potrebbe avere senso, ma se fosse dovuto a dati non validi di un nuovo tentativo sarebbe inutile ...

    
risposta data 21.12.2017 - 14:41
fonte
1

Approccio asincrono

Tradizionalmente, un'API responsabile dell'esecuzione di un'attività asincrona come la creazione di una riga nel database deve fornire un mezzo per comunicare il successo o l'insuccesso. Puoi farlo in due modi:

  • Tramite callback - che significa un'istanza di un'interfaccia che puoi chiamare in caso di successo o fallimento
  • Tramite una promessa - che è un valore restituito immediatamente dopo la chiamata che blocca quando è necessario il valore (il processo viene eseguito in parallelo finché non è necessario il valore contenuto all'interno).

Il chiamante può quindi gestire la promessa o il richiamo di conseguenza. Se sono necessarie più chiamate, è necessario garantire che si è terminato prima di chiamare il successivo.

Approccio di coda

Questo approccio significa garantire più responsabilità al tuo back-end. Il chiamante non si preoccupa più se l'attività è terminata o meno. La tua api lo fa. Significa che devi garantire che le attività siano eseguite nell'ordine della loro chiamata. Questo può essere fatto abbastanza facilmente aggiungendo richieste in una coda. Le prime voci vengono elaborate per prime e solo una volta che ciascuna attività precedente è terminata.

Rapporti

Nei casi entrambi , devi prepararti alla possibilità che più thread accedano allo stesso record. In altre parole, potrebbe ancora succedere che il processo A cancelli la riga 1 per prepararsi a essere reinserito, e il processo B tenti di aggiornare la riga 1 poco dopo. Questo tipo di problema viene normalmente affrontato utilizzando le transazioni, ovvero, si dispone di una serie di azioni raccolte in una singola transazione. La tua API deve garantire che tutti saranno eseguiti o nessuno di essi sarà.

Questo può essere fatto ordinando le transazioni stesse . Con ogni chiamata all'API in una determinata transazione, tale transazione aumenta di 1 operazione. Non viene eseguito nulla fino a quando non viene dato l'ordine di eseguire la transazione e l'ordine di esecuzione corretto delle transazioni si basa sulla creazione di detta transazione. Questo per garantire che gli effetti delle transazioni future non vengano visti dal corrente.

Devi essere in grado di eseguire tutte le azioni di una transazione con un mezzo per invertire ogni operazione. Se l'errore si verifica a metà, è necessario invertire ogni processo riuscito fino a quel punto. Se la transazione ha esito positivo, gli effetti delle modifiche devono essere visibili nel database. Se stai utilizzando un singolo thread per applicare queste modifiche, non è necessario altro per rendere visibili le modifiche perché il tuo ordine di transazione lo garantisce. Tuttavia, se usi più thread per questo, dovrai assicurarti che qualsiasi altra transazione non possa vedere gli effetti della transazione in esecuzione fino alla fine.

Conclusione

I libri sono stati scritti su questo argomento, in quanto questo non è molto diverso da come funzionano i database e come vengono eseguite le richieste di modifica dei dati. Questo sfiora leggermente l'argomento, ma spero che ti dia abbastanza per lavorare.

    
risposta data 21.12.2017 - 14:58
fonte
0

Indovina cosa? i database utilizzano un diario per annotare sequenzialmente le modifiche mentre provengono da più fonti.

È possibile avere uno di questi costrutti localmente in cui una modifica dall'interfaccia utente può accodare una richiesta (Crea, Aggiorna, Elimina). Un altro lavoratore può consumare questo giornale e trattare ogni richiesta con il server nello stesso ordine. Quando questa coda è vuota, tutte le modifiche vengono salvate.

Immagina un flusso di comandi che modificano una risorsa remota, in cui ogni comando può localizzare precisamente una risorsa remota e i campi nidificati in esso, comunicare se aggiungere o rimuovere e portare il nuovo valore:

+ tables/001/ [0.name] = "joe"
- tables/003/ [2]
- tables/001/ [3.age]
+ tables/002/ [0.age]  = 23
+ cars/009    [model]  = "chevy" 

È possibile utilizzare la connessione socket a 2 vie alla risorsa che si sta modificando e inviare / ricevere tali modifiche.

    
risposta data 22.12.2017 - 14:38
fonte

Leggi altre domande sui tag