Come approccio alla strutturazione quando leggere / scrivere oggetti in db?

1

Questo è un problema che ho affrontato in molte lingue nel corso degli anni (js, go, c, f #, haskell, python, ...), ma non ho ancora trovato un approccio generale per risolverlo. L'apprendimento dei modelli di coerenza nei database mi ha fatto capire che tutti i miei approcci finora stanno fallendo in modi diversi, di solito finisco con un sacco di condizioni di gara accidentali.

Il problema:

Sto recuperando i dati da un db e li sto memorizzando in strutture dati in memoria su un server. Non c'è limite al numero di parti di una singola base di codice che possono contenere quegli elementi alla volta, quindi potremmo contenere due copie contraddittorie di un singolo dato in memoria se non stiamo attenti. Alcuni aggiornamenti richiedono modifiche atomiche nel db (tentativi di accesso, ad esempio), mentre altri (come il nome visualizzato dall'utente) possono essere obsoleti o memorizzati nella cache per un po 'di tempo. Non voglio chiamare il db su ogni lettura / scrittura, perché è un modo lento e costoso.

Come ti avvicini di solito a questo problema? Quali sono i pro / contro del tuo approccio? Ci sono alcune migliori pratiche indipendenti dalla lingua in questo settore? Un modo per essere ragionevolmente sicuro del codice libero da gare di dati?

Tagging come ORM anche se non è strettamente relativo ai mapping OOP-RDBMS, perché non so come chiamare la cosa più generale.

    
posta Filip Haglund 17.07.2018 - 19:16
fonte

4 risposte

4

Puoi dare un'occhiata a Unità di lavoro :

[A unit of work] maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems.

Il pattern è descritto in Patterns of Enterprise Application Architecture

Per evitare le condizioni di gara, potresti usare un qualche tipo di meccanismo di blocco. Ci sono alcune strategie. Questa risposta la spiega bene, in sintesi:

  • Blocco ottimistico: quando si legge un record si prende una sorta di versione da esso (ad esempio l'ultima modifica data / ora). E quando è il momento di scrivere le modifiche, controlli se il record è stato modificato o meno, in caso affermativo, interrompi la transazione.
  • Blocco pessimistico: prima di leggere il record, crei un lucchetto in modo che nessun altro possa leggerlo / scriverlo mentre lavori con esso. Una volta che le modifiche sono state scritte o scartate, si rilascia il blocco.

Scegliere l'uno o l'altro dipende dal caso d'uso, principalmente in base al numero di client che si prevede di scrivere su una determinata risorsa nello stesso momento. Se ci sono molte serrature pessimistiche sarebbe la scelta.

La risposta parla di blocchi DB, ma puoi applicare l'idea per bloccare i blocchi (redis, memcached).

Sfortunatamente, AFAIK non esiste un modo semplice per "essere liberi dalle condizioni di gara". Dobbiamo pensare a ogni caso / transazione.

    
risposta data 17.07.2018 - 20:50
fonte
0

È necessario disporre di transazioni per aggiornare alcuni dati, è necessario controllare dove è letto e scritto. Un database se il "solito" posto per quello, ma può avere problemi di prestazioni se tutte le vostre richieste per tali dati devono colpire il database.

Un'opzione che ho visto utilizzata per alleviare questo problema consiste nell'introduzione di un livello di fabric di dati in grado di gestire anche le transazioni. Ad esempio, puoi guardare qualcosa come Apache Ignite che supporta transazioni

    
risposta data 17.07.2018 - 19:22
fonte
0

La soluzione che ho trovato che funziona è quella di utilizzare il DBMS come un sistema di gestione dei dati completo piuttosto che come un livello di persistenza. Come studi come mostrato - come Controllo della concorrenza ferale che si concentra su Ruby on Rails - implementando l'integrità dei dati nell'applicazione / ORM significa che sono soggetti a condizioni di gara.

Dovrebbe essere invece qualsiasi regola aziendale che può essere implementata come un vincolo di integrità dei dati all'interno del database. Idealmente, questi dovrebbero essere implementati in modo dichiarativo utilizzando i vincoli di verifica, esclusivi e di chiavi estranei disponibili nella maggior parte dei DBMS SQL. L'implementazione di questi nel motore DBMS dovrebbe includere qualsiasi meccanismo di controllo della concorrenza richiesto.

Sfortunatamente molti, se non tutti, i DBMS SQL non supportano la dichiarazione di asserzione SQL generica che consentirebbe la dichiarazione di qualsiasi vincolo di integrità dei dati di complessità arbitraria. Pertanto, li ho implementati in modo programmatico utilizzando i trigger e incluso il mio controllo della concorrenza utilizzando blocchi di avviso in PostgreSQL o DBMS_LOCK in Oracle .

Utilizzando anche tecniche di blocco ottimistiche o pessimistiche, sono sicuro di aver implementato correttamente un meccanismo di controllo della concorrenza che garantisce l'integrità dei dati senza condizioni di competizione.

    
risposta data 17.07.2018 - 23:03
fonte
0

Ci sono due classi principali di modi per affrontare questo problema:

  • chiusura
  • ignorando il problema

Quale è il meglio per te dipende interamente dalle tue particolari esigenze applicative e dalla tolleranza delle prestazioni. E spesso, all'interno di un'applicazione, per diversi tipi di dati, strategie diverse hanno senso.

BLOCCO

Il blocco è disponibile in molti modi (ottimistico, rigoroso, ecc.). Ma una cosa che accomuna tutti gli aromi, è la creazione di un enorme overhead delle prestazioni e un po 'di overhead di codifica / logica (complessità di implementazione).

Un altro meccanismo ortogonale che PUO funzionare bene con il blocco, è la classificazione / segregazione dei dati (sharding). In sostanza, si utilizzano alcune funzionalità dei dati per separare la posizione in cui sono archiviati (ad esempio se esiste un campo "id", utilizzare id% 3 e suddividere i dati su tre server di database), quindi è possibile implementare strategie di blocco leggero più economiche quei dati (e hanno meno conflitti di blocco).

IGNORA IL PROBLEMA

Per molti problemi di programmazione, questo non ha importanza. Se riesci a convincerti di essere in una di queste situazioni, rilassati e non ti preoccupare. Ad esempio, logging (o generazione / elaborazione di eventi). Qui le cose create sono immutabili e quindi non vengono mai aggiornate. Devi solo aggiungerne di nuovi.

    
risposta data 17.07.2018 - 23:29
fonte

Leggi altre domande sui tag