Ridondanza nel processo che legge e cancella dal database

0

Devo scrivere un servizio che legge i dati (una riga) da un database, invia messaggi SQS AWS e infine cancella i dati dal DB.

Lasciami spiegare usando un esempio. Ho una tabella di database D, il servizio S e la coda SQS Q. Ogni minuto, il servizio S, legge una riga (R1) da D, la analizza e invia un messaggio SQS a Q, e infine cancella la riga R1.

Il problema è che questo è un servizio critico e quindi ho bisogno di ridondanza. Inoltre, il messaggio SQS per ogni riga deve essere inviato esattamente una volta.

Possibili soluzioni a cui ho pensato (e problemi con esse):

  1. Processi multipli: Posso eseguire lo stesso script su più server. La probabilità che tutti loro si schiantino insieme è bassa. Tuttavia, questo può comportare l'invio di più messaggi SQS per la stessa riga. I processi P1 e P2 potrebbero leggere e inviare messaggi SQS per la stessa riga. Se elimino la riga, prima di inviare il messaggio SQS e il processo si blocca, potrei perdere definitivamente la riga senza inviare alcun messaggio.

  2. Processi multipli che funzionano con un ritardo: Posso eseguire più processi. P1 funziona come spiegato sopra. P2 opera con la verifica che elabori le righe che sono almeno (ad esempio 10 minuti). P3 opera su righe che sono almeno (ad esempio) vecchie di 20 minuti. Quindi se P1 si blocca, P2 può elaborare i dati. Se P1 e P2 si bloccano, P3 gestisce il carico, ecc. Il problema con questo approccio è che può causare ritardi nell'elaborazione.

Esistono schemi standard di progettazione / architettura che posso utilizzare per un simile problema?

Grazie!

    
posta Manas Paldhe 09.02.2017 - 19:34
fonte

2 risposte

4

Are there any standard design/architecture patterns that I can use for such a problem?

Transazioni e nuovi meccanismi.

Una transazione è un meccanismo che riesce completamente o fallisce completamente. Non lascia mai la tua operazione in uno stato incompleto; eseguirà l'intera operazione o nessuna di esse.

Potresti scrivere una stored procedure. Includere la messaggistica SQS nella stored procedure, con un ciclo tentativi finché non riesce o non riesce in modo permanente (dovrebbe avere esito positivo al 99 percento delle volte e fallire in modo permanente se si verifica un problema irrecuperabile). Avvolgere il tutto in una transazione di database e ripristinarlo se non si riesce a ottenere il messaggio SQS. Il tuo database gestirà automaticamente eventuali problemi di concorrenza.

La ridondanza è una preoccupazione ortogonale; è basato sulla tua infrastruttura. Assicurati che il tuo server di database sia robusto.

    
risposta data 09.02.2017 - 19:57
fonte
1

Senza un gestore di transazioni distribuito non è possibile effettuare garanzie "solo una volta" assolute.

Ci sono modi per aggirare questo. AWS code FIFO , ad esempio, rifiuterà i messaggi duplicati ricevuti entro 5 minuti . Puoi anche progettare il sistema di ricezione per scartare i duplicati.

Questo lascia il problema della ridondanza. Il mio approccio preferito è utilizzare un hot standby, utilizzando un sistema come ZooKeeper per identificare quando il primario va giù.

In alternativa, è possibile utilizzare un handshake del database. Per fare ciò aggiungi una colonna processed_by al record sorgente; manterrà un identificatore di processo univoco. Quindi, esegui il seguente all'interno di una transazione :

update  MYTABLE
set     processed_by = 'UNIQUE_PROCESS_IDENTIFIER'
where   processed_by is null;

select  -- rows
from    MYTABLE
where   processed_by = 'UNIQUE_PROCESS_IDENTIFIER'

Ciò richiede un indice su processed_by che supporti i valori null (o una piccola tabella contenente i messaggi da inviare) e aggiungerà carico al database. Forse più importante, se hai più consumatori, perdi le garanzie di ordinazione: mentre il consumatore # 1 elabora i messaggi, il produttore può aggiungere righe che vengono raccolte ed elaborate dal consumatore n. 2.

    
risposta data 10.02.2017 - 13:26
fonte