Aiuta a identificare il modello per reagire sugli aggiornamenti

4

C'è un'entità che viene aggiornata da fonti esterne. Gli eventi di aggiornamento sono a intervalli casuali. E l'entità deve essere elaborata una volta aggiornata. Più aggiornamenti possono essere multiplexati. In altre parole, è necessario che lo stato più attuale dell'entità venga elaborato.

C'è un punto di non ritorno durante l'elaborazione in cui lo stato corrente (e lo stato è consistente, cioè non viene effettuato alcun aggiornamento parziale) dell'entità viene salvato da qualche altra parte e l'elaborazione continua indipendentemente dagli aggiornamenti in arrivo.

Ogni conseguente serie di aggiornamenti deve attivare l'elaborazione, ovvero il sistema non dovrebbe dimenticare gli aggiornamenti. E per ogni entità non dovrebbe esserci più di una elaborazione in esecuzione (prima del punto di non ritorno), cioè lo stato dell'entità non dovrebbe essere elaborato più di una volta.

Quindi quello che sto cercando è un pattern per annullare l'elaborazione corrente prima del punto di non ritorno o abbandonare i risultati dell'elaborazione se arriva un aggiornamento. La sfida principale è ridurre al minimo le condizioni di gara e mantenere l'integrità.

L'entità si trova principalmente nel database con alcuni file su disco. E il sistema è in .NET con servizi Web e code di messaggi.

Ciò che mi viene in mente è una tabella simile a una coda di database. Un aggiornamento in arrivo inserisce una riga in quella tabella e l'elaborazione viene avviata. L'elaborazione raccoglie i dati necessari prima del punto di non ritorno e una volta raggiunta questa barriera esamina la tabella della coda e controlla se ci sono più aggiornamenti recenti per l'entità. Se ci sono nuovi aggiornamenti, l'elaborazione si arresta e i suoi dati vengono scartati. Altrimenti i dati di elaborazione sono persistenti e vanno oltre il punto di non ritorno.

Anche se sembra una soluzione per me non è abbastanza elegante e credo che questo scenario possa essere supportato da una sorta di middleware.

Se dovessi utilizzare le code di messaggi per questo, è necessario accedere all'API della coda nel punto di non ritorno per verificare l'esistenza di nuovi messaggi. E questo approccio manca anche di eleganza.

Esiste un nome per questo modello e una soluzione esistente?

    
posta Mike 24.10.2012 - 17:28
fonte

4 risposte

0

Sono stato in grado di implementare il modello in gran parte seguendo i consigli e le idee di Jimmy Hoffa.
Lo schema funziona già da alcuni mesi e funziona come segue.

  1. Ogni volta che l'entità viene aggiornata, inseriamo una nuova riga nella tabella EntityRevision. Questa tabella ha il campo RevisionId autoincrement (identità) che passiamo al Pre-Processing.
  2. Durante la pre-elaborazione estraiamo lo stato di entità associato a RevisionId in fase di elaborazione e lavoriamo con esso. Il punto qui è che evitiamo di utilizzare qualsiasi query che restituisce lo stato di Entità corrente perché è in continua evoluzione mentre Entità viene aggiornata. Al contrario, lo stato associato alla revisione non cambia mai ed è sicuro utilizzarlo durante gli aggiornamenti simultanei.
  3. L'Entity's RevisionId viene inviato alla coda di elaborazione offline dopo la pre-elaborazione. Usiamo le seguenti regole. Dire arrivato RevisionId è uguale a X

    a) Se non ci sono altre revisioni per la stessa entità nella coda, aggiungiamo X alla coda
    b) Se c'è già RevisionId che è Y per la stessa entità nella coda:

    • se Y > X, scartiamo X. In altre parole, non è necessario che la revisione precedente di X venga elaborata offline.
    • se X > Sì, rimuoviamo Y dalla coda e X alla coda. Poiché Y è precedente a X, lo sostituiamo con X.

    Facciamo in modo che le operazioni sulla coda vengano eseguite in ordine seriale in modo che al massimo un processo / thread modifichi la coda in qualsiasi momento. Per ora usiamo Mutex nelle operazioni di coda.

  4. L'elaborazione offline esegue il polling della coda su una pianificazione periodica e fa ciò che deve fare con le revisioni nella coda. Ancora una volta usiamo qui solo lo stato di entità associato alla sua revisione.

    Sebbene garantiamo che ci sia la Revisione corrente nella coda pre-elaborata finora, non siamo ancora protetti dalla stessa Entità in fase di aggiornamento o aggiornamento pre-elaborato durante o subito dopo l'elaborazione offline in corso. In tal caso, un aggiornamento dovrà attendere nella coda per il successivo avvio dell'elaborazione offline. Ma va bene, non possiamo vietare gli aggiornamenti :) In realtà quegli aggiornamenti sono l'essenza del sistema.

risposta data 19.06.2013 - 12:43
fonte
1

Separerei il processore "point-of-no-return" dal pezzo pre-setup. Un servizio preleva gli aggiornamenti e fa tutto il necessario per essere pronto per l'elaborazione offline, e poi prima di passarlo al processore offline controlla solo il database o se è su una singola macchina che potresti usare segnali, in .NET EventWaitHandles chiamato per l'ID entità per vedere se sono arrivati nuovi aggiornamenti. In caso affermativo, il il pre-processore torna indietro per iniziare con i nuovi aggiornamenti introdotti, in quanto rende di nuovo tutto pronto per il processore offline. Ogni volta che arriva al punto di elaborazione offline esegue questo controllo.

    
risposta data 24.10.2012 - 18:10
fonte
1

The processing gathers necessary data before the point of no-return and once it reaches this barrier it looks into the queue table and checks whether there're more recent updates for the entity. If there are new updates the processing simply shuts down and its data is discarded. Otherwise the processing data is persisted and it goes beyond the point of no-return.

A seconda della frequenza degli aggiornamenti ricevuti, il sistema può entrare nei periodi di inedia - dove gli aggiornamenti appena elaborati vengono scartati continuamente perché ne vengono ricevuti di nuovi.

Invece di buttare via i calcoli, puoi semplicemente mantenere una pila di uscite generate.

Dai un'occhiata a LMAX Architecture: link

    
risposta data 04.11.2012 - 20:19
fonte
0

Supponendo che tu stia bene limitando le opzioni del tuo repository di dati a Microsoft SQL Server, puoi scegliere di usare Service Broker per gestire i tuoi messaggi e amp; accodamento.

Poiché tutto questo verrebbe incapsulato all'interno del motore di database, non ci sarebbe bisogno di alcun tipo di chiamate API esterne dal punto di non ritorno. Tutta la logica potrebbe essere scritta in stored procedure (con T-SQL o come procedure CLR). Inoltre, con Attivazione di Service Broker , puoi avere altri programmi (es. il tuo eseguibile) esegui su richiesta, ogni volta che c'è del lavoro da fare.

Come ulteriore vantaggio, Service Broker è facilmente scalabile, quindi puoi scaricare qualsiasi elaborazione dati su un altro server (s) e amp; mantieni il tuo server di database primario impantanato da qualsiasi carico di elaborazione dati irregolare - installa le tue istanze multiple & indirizzare Service Broker agli endpoint appropriati .

Tuttavia, alcuni degli svantaggi dell'utilizzo di Service Broker sono:

  • Curva di apprendimento aggiuntiva per gli sviluppatori (apprendimento di una nuova tecnologia).
  • Più complicato da risolvere per qualsiasi supporto tecnico di tipo non DBA.
  • Richiede Versione standard o successiva (con SQL Server 2012) - non disponibile con l'Express Edition (ovvero la versione gratuita).
risposta data 04.11.2012 - 01:37
fonte