Un thread per tutte le operazioni del database o un thread per ogni operazione db?

0

Sto lavorando su un'applicazione server che dovrebbe gestire molte richieste. C'è un thread per ogni richiesta e ogni richiesta ha un'operazione di database.

Creare una connessione per ogni richiesta e fare l'operazione DB perderà tempo. Le operazioni di I / O su ogni thread possono causare molti switch di contesto che faranno perdere tempo anche

Penso che sia meglio avere un thread per le operazioni DB (chiamato DB_Thread). quando arriva una nuova richiesta, verrà creato un nuovo thread per la richiesta, il nuovo thread aggiungerà la sua operazione in un elenco e attenderà. DB_Thread eseguirà operazioni dall'elenco. nuovo thread attendi fino al termine dell'operazione. in questa situazione c'è un thread con operazioni di I / O e quando altri thread sono in attesa di DB_Thread, ci sono molti meno switch di contesto

È una buona soluzione? o no ? e perché?

    
posta G3ntle_Man 27.11.2017 - 01:14
fonte

2 risposte

3

Is it a good solution ? or not ? and why ?

I database sono stati tra noi per molto tempo e molte persone hanno già pensato per noi;)

Hai un problema di Serializazzione transazionale .

Fondamentalmente, rispondi alla domanda:

"Che cosa succede ai dati quando un database riceve molte transazioni (ciascuna con un'operazione di lettura / scrittura / creazione / distruzione)?"

E hanno già risolto con Bloccaggio a due fasi controllo della concorrenza.

Quindi, indipendentemente dal modo in cui viene implementato il livello dell'applicazione, ciascun database dispone già di Serializability e Concurrency Control all'interno di esso.

Con questo in mente, lascia la tua domanda in analisi ...

Creating connection for each request and doing the DB operation will waste time.

Per evitare questo problema, puoi utilizzare i pool di connessione del database che avranno connessioni libere per le tue richieste in arrivo e ne creeranno automaticamente altri automaticamente.

I/O operations on each thread may cause many context-switches that will waste time too.

A meno che la tua applicazione non abbia alcuni vincoli, il costo dell'interruttore di contesto è veramente piccolo (1 ~ 7 microsecondi) - come discusso su Stack Overflow.

Per migliorare le prestazioni dell'IO, puoi utilizzare le chiamate native per eseguire l'IO a un livello inferiore, come i buffer / canali NIO java, i file di mapping della memoria per evitare Spazio utente copia, (e così via ...)

I think it's better to have one thread for DB Operations (named DB_Thread ). when a new request arrives, a new thread will be created for the request, the new thread will add it's operation in a list and wait. DB_Thread will do operations from the list. new thread wait until the operation ends. in this situation there is one thread with I/O operations and when other threads are waiting for DB_Thread, there is much fewer context-switches

Questo crea un inutile collo di bottiglia , poiché se questo (singolo) DB_Thread è occupato con un po 'di lavoro (di un filo).

E peggio ancora, TU devi gestire tutta la sincronizzazione di tutto questo. Quando si verificano transazioni, il database crea già un grafico di precendenza per verificare se lo stato corrente del database è corretto o meno. Se (per qualche motivo) rileva uno stato incoerente, inizierà a risolverlo e il rollback (alcune se possibile) cambierà nuovamente in uno stato consistente.

Ciò causerà il fallimento delle tue transazioni e ripristinerà le modifiche fatte da loro.

A livello dell'applicazione, i thread ricevono una notifica di errore e devono implementare la gestione dell'errore.

Se sembra troppo complicato, è! ;)

Quindi questa è una ragione più che sufficiente per non andare in quella direzione.

Nel tuo caso, TU dovrà implementare che il tuo DB_Thread non si blocchi in attesa che il database serializzi tutte le operazioni e impegni la tua transazione e informi ogni thread che la transazione DB ha successo o non.

Keep It Stupidly Simple (KISS), non reinventare il pozzo.

  1. Consenti alle transazioni del database di essere gestite dal database.
  2. Consenti alle transazioni IO di essere gestite da una soluzione / libreria IO / (...)
  3. Se è necessario sincronizzare entrambe le transazioni, utilizzare un gestore delle transazioni in grado di gestire tale situazione.

Concentrati maggiormente sui test di integrazione per assicurarti che tutto funzioni.

    
risposta data 27.11.2017 - 16:50
fonte
3

Le operazioni di database in genere consistono in più fasi e consentono una discreta esecuzione parallela. Il tuo singolo thread lo bloccherà.

Hai ragione che creare una nuova connessione per ogni richiesta è una grande perdita di tempo.

Farei le operazioni del database sui thread di richiesta, ma uso un pool di connessioni con un numero configurabile di connessioni.

Quindi non si verificano problemi di sincronizzazione dei thread (vengono gestiti nel pool di connessioni) e si ha un'implementazione diretta delle richieste. Il numero di connessioni nel pool controlla la quantità di parallelismo. Se ricevi troppe richieste, le richieste attenderanno fino a quando la prossima connessione non sarà disponibile.

Puoi (e dovresti) confrontare la scalabilità con diversi numeri di connessioni per scoprire come "parallelo" è il tuo database.

    
risposta data 27.11.2017 - 15:32
fonte

Leggi altre domande sui tag