Microservizi e join di database


112

Per le persone che stanno suddividendo le applicazioni monolitiche in microservizi, come gestisci il connubio della rottura del database. Le applicazioni tipiche su cui ho lavorato fanno molta integrazione con il database per motivi di prestazioni e semplicità.

Se hai due tabelle che sono logicamente distinte (contesti limitati se vuoi) ma spesso esegui elaborazioni aggregate su grandi volumi di quei dati, allora nel monolite è più che probabile che eviti l'orientamento agli oggetti e utilizzi invece lo standard del tuo database Funzionalità JOIN per elaborare i dati nel database prima di restituire la visualizzazione aggregata al livello dell'app.

Come giustifichi la suddivisione di tali dati in microservizi dove presumibilmente ti verrà richiesto di "unire" i dati tramite un'API piuttosto che nel database.

Ho letto il libro Microservices di Sam Newman e nel capitolo sulla suddivisione del monolite fornisce un esempio di "Rompere le relazioni di chiavi esterne" in cui riconosce che fare un join attraverso un'API sarà più lento, ma prosegue dicendo se la tua applicazione è comunque abbastanza veloce, importa che sia più lenta di prima?

Questo sembra un po 'superficiale? Quali sono le esperienze delle persone? Quali tecniche hai utilizzato per rendere accettabili i join API?


2
Bella domanda, sto riscontrando lo stesso problema e ho finito per avere una visione materializzata e partecipare a questo. Non mi piace, ma credo che sarà una sfida con Micro Services. Non c'è un modo giusto per farlo, è solo una scelta di design da fare. So che molte persone dicono che possiamo avere una visione materializzata, ma le risposte aggregate diventano un problema. Fammi sapere se hai trovato qualcosa di meglio.
PavanSandeep

So che è vecchio, ma è qualcosa che risolve graphql? Sto anche esaminando questo aspetto per una migrazione segmentata, e sembra che graphql sia il modo per renderlo senza soluzione di continuità.
themightybun

Ad un certo punto dovresti renderti conto che essere dogmatici non è la strada da percorrere. GraphQL è un buon esempio di aggregazione al di fuori dell'origine dati e di solito funziona bene.
Christian Ivicevic

Risposte:


26
  • Quando le prestazioni o la latenza non contano troppo (sì, non sempre ne abbiamo bisogno) va benissimo usare solo semplici API RESTful per eseguire query sui dati aggiuntivi di cui hai bisogno. Se è necessario eseguire più chiamate a diversi microservizi e restituire un risultato, è possibile utilizzare il pattern API Gateway .

  • Va benissimo avere la ridondanza negli ambienti di persistenza Polyglot . Ad esempio, puoi utilizzare la coda di messaggistica per i tuoi microservizi e inviare eventi di "aggiornamento" ogni volta che modifichi qualcosa. Altri microservizi ascolteranno gli eventi richiesti e salveranno i dati in locale. Quindi, invece di eseguire query, conservi tutti i dati richiesti nella memoria appropriata per un microservizio specifico.

  • Inoltre, non dimenticare il caching :) Puoi usare strumenti come Redis o Memcached per evitare di interrogare altri database troppo spesso.


25
Tutti buoni suggerimenti, ma trovo ancora difficile razionalizzare, forse perché siamo così abituati a fare molte elaborazioni nel database. La nostra applicazione corrente ha procedure memorizzate complicate che elaborano grandi volumi di dati e quindi restituiscono un piccolo set di risultati. In un'architettura di microservizi, penserei che queste entità dovrebbero essere suddivise in diversi contesti limitati. Sappiamo che l'approccio attuale è brutto ma è difficile giustificare il ripristino di tutti i dati al livello dell'app per elaborarli. Forse sarebbe d'aiuto una maggiore denormalizzazione o viste aggregate pre-elaborazione.
Martin Bayly

1
Si, vedo. L'approccio ai microservizi non è per tutti e dovresti applicarlo con attenzione. Probabilmente puoi iniziare con modifiche più piccole.
sap1ens

Probabilmente i programmatori StackExchange sarebbero stati un posto migliore per porre questa domanda: programmers.stackexchange.com/questions/279409/… e altre domande contrassegnate con microservices programmers.stackexchange.com/questions/tagged/microservices
Martin Bayly

9

È corretto che i servizi dispongano di copie replicate di sola lettura di determinati dati di riferimento da altri servizi.

Dato che, quando provo a rifattorizzare un database monolitico in microservizi (invece di riscriverlo) lo farei

  • creare uno schema db per il servizio
  • creare viste * con versione ** in quello schema per esporre i dati di quello schema ad altri servizi
  • si unisce contro queste visualizzazioni di sola lettura

Ciò ti consentirà di modificare in modo indipendente i dati / la struttura della tabella senza interrompere altre applicazioni.

Piuttosto che utilizzare le viste, potrei anche prendere in considerazione l'utilizzo di trigger per replicare i dati da uno schema a un altro.

Questo sarebbe un progresso incrementale nella giusta direzione, stabilendo le giunzioni dei tuoi componenti e un passaggio a REST può essere fatto in seguito.

* le visualizzazioni possono essere estese. Se è necessaria una modifica sostanziale, creare una v2 della stessa vista e rimuovere la vecchia versione quando non è più necessaria. ** o Funzioni con valori di tabella o Sprocs.


5

CQRS --- Command Query Aggregation Pattern è la risposta a questo secondo Chris Richardson. Lascia che ogni microservizio aggiorni il proprio modello di dati e generi gli eventi che aggiorneranno la vista materializzata con i dati di join richiesti dai microservizi precedenti.Questo MV potrebbe essere qualsiasi DB NoSql o Redis o elasticsearch ottimizzato per le query. Questa tecnica porta a un'eventuale coerenza che sicuramente non è male ed evita i join laterali dell'applicazione in tempo reale. Spero che questo risponda.


2

Separerei le soluzioni per ambito di utilizzo, diciamo operativo e di reporting.

Per i microservizi che operano per fornire dati per singoli moduli che richiedono dati da altri microservizi (questo è il caso operativo), penso che l'utilizzo di API join sia la strada da percorrere. Non andrai per grandi quantità di dati, puoi fare l'integrazione dei dati nel servizio.

L'altro caso è quando è necessario eseguire query di grandi dimensioni su grandi quantità di dati per fare aggregazioni, ecc. (Il caso di segnalazione). Per questa esigenza, penserei di mantenere un database condiviso, simile al tuo schema originale e aggiornarlo con gli eventi dei tuoi database di microservizi. Su questo database condiviso è possibile continuare a utilizzare le procedure memorizzate che farebbero risparmiare sforzi e supportare le ottimizzazioni del database.


1

In Microservices crei diff. leggi i modelli, quindi ad esempio: se hai due diff. contesto delimitato e qualcuno vuole cercare su entrambi i dati, quindi qualcuno deve ascoltare gli eventi da entrambi i contesti limitati e creare una vista specifica per l'applicazione.

In questo caso ci sarà più spazio necessario, ma non saranno necessari né join né join.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.