2013-05-08 18 views
5

Il mio team deve trovare una soluzione al seguente problema:Come posso garantire la coerenza degli aggregati con alta disponibilità?

La nostra applicazione consente agli utenti di visualizzare le vendite totali per l'impresa, totali per prodotto, totali per regione, totali per regione x prodotto, totali per regioni x divisione, ecc. Hai capito l'idea. Ci sono così tanti valori che devono essere aggregati per ottenere molti di quei totali che non possono essere calcolati al volo - dobbiamo pre-aggregarli per fornire tempi di risposta decenti, un processo che richiede circa 5 minuti.

Il problema, che pensavamo fosse comune ma non trova riferimenti, è come consentire aggiornamenti alle varie vendite senza chiudere gli utenti. Inoltre, gli utenti non possono accettare la coerenza finale - se eseguono il drill-down su un totale di 12, vedono meglio i numeri che ne sommano fino a 12. Quindi abbiamo bisogno di Coerenza + Disponibilità.

La soluzione migliore finora descritta è quella di indirizzare tutte le query a un database ridondante, "B" (ottimizzato per le query) mentre gli aggiornamenti vengono indirizzati al database principale, "A". Quando decidiamo di dedicare i 5 minuti necessari per aggiornare tutti gli aggregati, aggiorniamo il database "C", che è un altro database ridondante come "B". Quindi, le nuove sessioni utente vengono indirizzate a "C", mentre le sessioni utente esistenti continuano a utilizzare "B". Alla fine, avvisando chiunque è andato via usando "B", uccidiamo le sessioni su "B" e ri-aggregiamo lì, scambiando i ruoli di "B" e "C". Tipico scenario di fermata-arresto.

Siamo sorpresi del fatto che non siamo in grado di trovare alcuna discussione al riguardo e siamo preoccupati che stiamo sovrastimando questo problema o forse non è il problema che pensiamo che sia. Qualsiasi consiglio è molto apprezzato.

+0

Abbiamo avuto molti pre-aggregati, ma eravamo contenti della coerenza finale, quindi non abbiamo dovuto inventare trucchi intelligenti. Il tuo approccio proposto sembra fattibile. –

+0

@sergio Grazie!Il tuo ultimo commento mi dà speranza. – RonR

risposta

2

Questo era un problema interessante, quindi ci ho pensato sul treno, e mi è venuta l'idea di archiviare un timestamp per ogni riga del database su cui vi siete aggregati. (Penso che questa tecnica abbia un nome, ma mi sfugge e googling non lo trova ...)

Il timestamp indica quando questa riga è stata inserita. Inoltre:

-Se le righe possono essere aggiornate, si avranno due "versioni" della riga contemporaneamente, una più recente dell'altra.

-Se le righe possono essere eliminate, è necessario che sia presente una riga 'versione eliminata' che specifica quando è stata eliminata.

Ora si possono fare cose come ad esempio:

1) Di che si aggiornano gli aggregati al 1 gennaio 2000 a mezzanotte. È possibile avere viste della tabella che restituiscono i dati della tabella come se fosse la mezzanotte del 1 gennaio 2000, ignorando tutti gli inserti/aggiornamenti/eliminazioni più recenti. Ora gli aggregati sono aggiornati come i dati nella vista E puoi continuare ad aggiungere dati alla tabella sottostante.

2) Io non so come fattibile/facile da garantire che sia affidabile questo sarebbe, ma si potrebbe avere 'aggregati in modo differenziale calcolati' in cui il 2 Gennaio 2000 a mezzanotte, si prendono gli aggregati del 1 gennaio 2000 a mezzanotte e aggiornamento solo con i dati che sono stati modificati da quel momento, risparmiandoti di ricalcolare così tanti dati storici.(Naturalmente, diventa più difficile una volta considerate le righe aggiornate o cancellate che sono più vecchie di 24 ore)

3) Ogni volta che si aggiornano gli aggregati, è possibile unire le righe aggiornate e cancellate con la loro versione precedente e ottenere elimina la versione precedente, quindi devi solo mantenere duplicati di righe quando ne hai bisogno per separare le righe che sono state aggregate e le righe che non lo sono (questo significa anche che, ad esempio, se tutti i tuoi aggregati vengono eseguiti contemporaneamente, e aggiorni una riga tre volte in rapida successione, devi solo mantenere la riga di aggiornamento più recente)

+0

Sì, questo è chiamato "controllo delle versioni delle righe", ma non vedo come sarebbe utile nella nostra situazione. Gli aggiornamenti si verificherebbero in "A", ma abbiamo ancora bisogno di avere "B" perché "B" ha uno schema completamente diverso ottimizzato per le query. – RonR

+0

@RonR Beh, se riesci a sbarazzarti di C e hai ancora alta disponibilità + consistenza, è questo il punto, vero? Quando calcoli nuovi aggregati, li aggiungi con il nuovo timestamp che indica che sono validi per i dati fino a quel timestamp - se usi ancora i vecchi aggregati, fai ancora riferimento solo alle righe fino a quel timestamp, se passi a nuovi aggregati che fai riferimento a righe fino a quel timestamp. – Patashu

+0

D'accordo che questo è il punto. Ho interpretato erroneamente la tua risposta iniziale come suggerendo che tutto poteva essere fatto solo con "A". – RonR

2

Se gli aggiornamenti non possono essere calcolati in tempo reale, la memorizzazione nella cache dei risultati viene eseguita come in un altro database. risolvere il problema della disponibilità con tempi di risposta più rapidi.

Per coerenza, è possibile utilizzare una qualche forma di isolamento della transazione. Ad esempio, MySQL supporta un numero di diversi livelli di transazione, di cui REPEATABLE READ potrebbe avvicinarsi a fornire una certa coerenza in una singola transazione. Se una transazione può essere lasciata aperta per più richieste mentre gli utenti eseguono il drill down per vedere i dati, vedono effettivamente un'istantanea dello stato del database a partire dalla prima richiesta.

In un senso più generico, sei solo dopo un handle che ai dati che viene fornito dal client per indicare un insieme coerente. Come nella risposta di Patashu, l'handle per un client che richiede un insieme di aggregati potrebbe essere basato sul tempo. La prima fase dell'interazione con il cliente sarebbe quella di ottenere una gestione degli ultimi dati aggregati, ad esempio l'ora corrente. Se poi passasse quella maniglia con ogni richiesta. Quando vengono fatte richieste al server, utilizza l'handle per determinare quale serie di dati aggregati restituire. Piuttosto che avere entrambi i server "B" e "C", tutti i dati aggregati potrebbero essere memorizzati nel server "B", con tutti i dati aggregati contenenti le informazioni sull'impugnatura. Ciò consente quindi le richieste a un singolo server per i dati aggregati sia nuovi che vecchi. A un certo punto, i vecchi dati aggregati potrebbero essere eliminati da "B".

Forse una ricerca sull'isolamento della transazione mostrerà più risultati per la discussione sulla coerenza.

+0

Hmmm.Questo ha le possibilità definite come un modo per fare a meno della necessità di dover scambiare 2 database, al costo di qualche complessità aggiuntiva. grazie! – RonR

1

Penso che tu sia alla ricerca di concetti Data Warehousing

In informatica, un data warehouse o impresa data warehouse (DW, DWH, o EDW) è un database utilizzato per il reporting e l'analisi dei dati. È un repository centrale di dati che viene creato integrando i dati da una o più origini disparate. I data warehouse memorizzano anche come dati storici e vengono utilizzati per la creazione di rapporti di tendenza per il rapporto di gestione senior , ad esempio i confronti annuali e trimestrali.

...

differenza data warehouse ETL-based, i dati di origine integrati sistemi e il magazzino dati sono integrati in quanto non v'è alcuna trasformazione dei dati dimensionali o di riferimento. Questa architettura di magazzino integrata dei dati supporta il drill down dei dati aggregati del data warehouse ai dati transazionali dei sistemi di origine dati integrati .

+0

sì, questa è la metà della soluzione: avere un database completamente separato progettato per le query di aggregati, trend, ecc. Ma l'altra metà è la domanda più ampia: come si aggiorna il dw pur garantendo coerenza? – RonR

Problemi correlati