Come gestire gli aggiornamenti simultanei per lo stesso record in un sistema distribuito

3

Sto cercando di capire la migliore soluzione per il seguito. Qualsiasi aiuto sarebbe fantastico.

Quindi in pratica ho un servizio (che può essere ridimensionato orizzontalmente), che ascolta una coda. Ogni messaggio ricevuto verrà inviato a un lavoro e elaborato contemporaneamente.

Il lavoro sarà (nello stesso ordine):

  1. Genera alcuni dati in base al carico utile del messaggio
  2. Memorizza i dati su Redis
  3. Invia i dati a un altro servizio

Il mio problema si verifica quando viene ricevuto un altro messaggio per lo stesso record logico (stesso record di tabella ma con dati modificati).
Devo assicurarmi che l'ultima versione dei dati sia memorizzata nella cache su Redis e inviata al servizio successivo nello scenario in cui vengono elaborati 2 o più messaggi con lo stesso ID record. Quindi evita che un lavoro con una vecchia versione del payload stia sovrascrivendo l'ultimo.

Penso di utilizzare un meccanismo di blocco distribuito, non sono sicuro che sia efficiente, soprattutto quando voglio che l'ultima versione venga inviata al prossimo servizio il più rapidamente possibile.
Forse in qualche modo cancellare un lavoro per un carico utile obsoleto invece di bloccare l'intero lavoro? Usare Redis pubsub per comunicare tra il servizio (quando si ridimensiona) o avere un modo migliore?

    
posta Alan 30.08.2018 - 15:03
fonte

2 risposte

1

Se fossi in te, creerei un meta record per messaggio contenente i seguenti componenti:

  • Chiave del record logico
  • Timestamp di questo messaggio
  • Valore del carico utile

consente a ciascun processo di creare il proprio record in un archivio dati temporaneo e invalida l'archivio dati permanente. quindi consentire un processo di pulizia (chiamarlo l'arbitro) per decidere l'ultima versione e promuoverlo per essere visibile nell'archivio dati finale.

Questa impostazione ottimizza per le scritture.

ovviamente questa tecnica ha limitazioni di scala, al di sotto di una certa soglia dovrebbe raggiungere una coerenza finale.

quando recuperi i tuoi dati, li estrai da un sistema di recupero prioritario tale;

  • Se l'archivio dati permanente non è invalidato, selezionalo
  • Se l'archivio dati è invalidato, seleziona i dati dal tuo archivio dati temporaneo, ordinati per data e ora decrescente
risposta data 28.12.2018 - 18:48
fonte
0

Correggimi se sbaglio, ma sembra che tu abbia il seguente flusso di dati

Message Queue: InBox
Service1 : read message from InBox
           process InBox.Id
           save result to Redis
           send message to S1Out with S1Out.Id = Start.Id

Message Queue: S1Out
Service2 : read message from S1Out
           read data from Redis with S1Out.Id
           save data to DB

Il problema è che puoi ottenere 2 messaggi InBox per lo stesso Id e i dati redis verranno sovrascritti dalla seconda richiesta elaborata. Causando il servizio 2 comportarsi in modo strano.

In realtà vorrei inviare tutti i dati richiesti dal servizio 2 nel messaggio S1Out piuttosto che fare in modo che S2 cerchi i dati nella cache redis. (Grandi messaggi)

Questo elimina il problema e un punto centrale di errore / collo di bottiglia della cache.

Tuttavia. Un approccio alternativo sarebbe quello di generare un nuovo Id per ogni elemento salvato nella cache e aggiungere quell'Id al messaggio. Ciò consente a Service 2 di raccogliere i dati corretti per il lavoro.

Il secondo problema di avere un lavoro ridondante che fluisce attraverso la coda è più difficile da gestire finché non colpisci una risorsa condivisa.

Nel mio esempio Service 2 salva i dati in un DB. A questo punto è in grado di verificare se il suo lavoro è ridondante. Conosce il timestamp dal messaggio originale e il database conosce il timestamp dei messaggi elaborati, quindi il servizio può confrontare e saltare o abbandonare il lavoro scaduto.

In alternativa, è possibile aggiungere un altro 'Router Worker' il cui unico lavoro è leggere da S1Out, conservare un buffer di messaggi e rimuovere o riordinare lavori ridondanti e postare su S1Out2. Ma questo diventa un altro punto centrale di fallimento; come se ne avessi due, non possono visualizzarsi reciprocamente.

Il mio approccio preferito è quello di elaborare tutti i messaggi e di eliminare effetti ridondanti solo quando causerebbero un vero problema. (cioè, non solo essere più ottimale dell'uso della CPU)

    
risposta data 30.08.2018 - 15:31
fonte

Leggi altre domande sui tag