9

Otteniamo chiamate simultanee alla nostra applicazione Web da un fornitore e sospettiamo che ci stia causando aggiornamenti persi perché vengono elaborati nello stesso momento su macchine diverse.Come posso elaborare la maggior parte dei lavori in parallelo ma serializzare un sottoinsieme?

Abbiamo bisogno di serializzare l'elaborazione di quelle chiamate se e solo se interessano lo stesso record utente.

Un mio collega ha proposto un flusso AWS Kinesis in cui utilizziamo l'ID utente come chiave di partizione. L'idea è che la stessa chiave di partizione collochi il record nello stesso frammento. Ogni frammento viene elaborato da un solo operatore e non ci saranno problemi di concorrenza. In base alla progettazione, sarà garantito che i record appartenenti allo stesso utente non vengano elaborati in parallelo. Questa soluzione ridimensiona e risolve il problema, ma ci restituirà almeno uno sprint.

Stiamo cercando una soluzione che possiamo implementare più rapidamente.

Altre soluzioni che abbiamo discusso finora:

  1. che ritardare l'elaborazione dei callback, potenzialmente da un periodo di tempo casuale. In questo scenario, è ancora possibile (anche se meno probabile) che diversi lavoratori lavorino allo stesso utente nello stesso momento.
  2. Qualsiasi sistema di accodamento ha il difetto di essere limitato a un solo operatore o al rischio di elaborazione parallela o uguale a quanto indicato in (1).

Siamo su uno stack Rails con MySQL e preferiamo AWS per le nostre soluzioni.

Esiste una soluzione a questo problema che consentirà di ottenere risultati più rapidi rispetto al passaggio a Kinesis?

risposta

0

In pratica si cercano i blocchi distribuiti denominati, in modo da poter applicare l'elaborazione seriale.

Se si è in AWS, è possibile inviare un record a DynamoDB con ogni ID cliente.

Ogni volta che si ottiene un record per l'elaborazione, eseguire una lettura coerente (vedere la sezione sulle concomitanze qui: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/APISummary.html).

Se è presente un record, aggiungere il messaggio (scrittura coerente). Avere il processo che si sta elaborando fa una lettura dopo averlo fatto, e se ci sono messaggi aggiunti al record della dinamo, elaborarli in serie. Infine cancella il record.

È possibile che si ottengano condizioni di gara, quindi è necessario eseguire un back-off e riprovare. Non so quale sia il tuo volume, ma Dynamo è piuttosto veloce, quindi le probabilità di colpire questo più di un paio di volte sono scarse. Se fallisce troppe volte, potrebbe essere necessario scaricare le cose in una coda di errori per la pulizia, ma è piuttosto improbabile. Soprattutto se il tuo volume ti consente di considerare soluzioni come il ritardo arbitrario nell'elaborazione dei messaggi.

0

Solo alcuni input teorico:

Se ha callback tecnicamente indipendenti è necessario un identificatore semantica che li contraddistingue come dipendente o indipendente e un id sequenza che assicura l'ordine di esecuzione. L'ID utente non è sufficiente. Come si può garantire l'ordine di esecuzione del database corretto delle richieste Web parallele di un utente?

Se si dispone di ID di transazione univoci, è possibile applicare livelli di isolamento come la serializzazione. Ma in questo caso non sei invulnerabile neanche contro i "tuoi" aggiornamenti persi. Accadranno anche quando si utilizza la serializzazione a meno che non si abbia un numero di sequenza (versione) e un meccanismo di blocco.

Assicurati di parlare di "sovrascrittura di dati non inviati" se intendi "aggiornamenti persi" per evitare le incomprensioni. Questo sarà gestito con almeno il livello di isolamento "lettura ripetibile".