Non esiste una soluzione chiara perché dipende interamente dal contesto, in particolare dalle dimensioni che il sistema dovrebbe ridimensionare e dai problemi reali. Il database è davvero il tuo collo di bottiglia?
Questa risposta (purtroppo piuttosto lunga) leggerà un po 'come "i microservizi sono cattivi, i monoliti per la vita!", Ma non è questa la mia intenzione. Il mio punto è che i microservizi e i database distribuiti possono risolvere vari problemi, ma non senza problemi propri. Al fine di presentare una valida argomentazione per la tua architettura, devi dimostrare che questi problemi non si applicano, possono essere mitigati e che questa architettura è la scelta migliore per le tue esigenze aziendali.
I dati distribuiti sono difficili.
La stessa flessibilità che consente un miglior ridimensionamento è il rovescio della medaglia delle garanzie più deboli. In particolare, i sistemi distribuiti sono molto più difficili da ragionare.
Gli aggiornamenti atomici, le transazioni, la coerenza / integrità referenziale e la durata sono estremamente preziosi e non devono essere rinunciati in modo avventato. È inutile disporre di dati se sono incompleti, obsoleti o assolutamente errati. Quando hai ACID come requisito aziendale ma stai utilizzando una tecnologia di database che non è in grado di offrirlo immediatamente (ad es. Molti database NoSQL o un'architettura DB per microservizio), la tua applicazione deve colmare il vuoto e fornire tali garanzie.
Questo non è impossibile da fare, ma difficile da ottenere. Molto difficile. Soprattutto in un'impostazione distribuita in cui sono presenti più writer per ciascun database. Questa difficoltà si traduce in un'alta probabilità di bug, inclusi eventualmente dati persi, dati incoerenti e così via.
Ad esempio, si consideri la lettura delle analisi Jepsen di noti sistemi di database distribuiti , forse a partire dall'analisi di Cassandra . Non capisco la metà di tale analisi, ma il TL; DR è che i sistemi distribuiti sono così difficili che persino i progetti leader del settore a volte li sbagliano, in modi che possono sembrare ovvi col senno di poi.
I sistemi distribuiti implicano anche un maggiore sforzo di sviluppo. In una certa misura, c'è un compromesso diretto tra i costi di sviluppo o la caduta di denaro su hardware più robusto.
Esempio: riferimenti penzolanti
In pratica, non dovresti guardare l'informatica ma i requisiti della tua azienda per vedere se e come ACID può essere rilassato. Ad esempio, molte relazioni di chiave esterna potrebbero non essere così importanti come sembrano. Considera una relazione prodotto - categoria n: m. In un RDBMS potremmo usare un vincolo di chiave esterna in modo che solo i prodotti esistenti e le categorie esistenti possano far parte di quella relazione. Cosa succede se introduciamo servizi di prodotti e categorie separati e un prodotto o una categoria vengono eliminati?
In questo caso, potrebbe non essere un grosso problema e possiamo scrivere la nostra applicazione in modo da filtrare tutti i prodotti o le categorie che non esistono più. Ma ci sono dei compromessi!
Si noti che ciò potrebbe richiedere un livello di applicazione JOINsu più database / microservizi, che sposta semplicemente l'elaborazione dal server di database all'applicazione. Ciò aumenta il carico totale e deve spostare dati extra attraverso la rete.
Questo può fare casino con l'impaginazione. Ad esempio, richiedi i prossimi 25 prodotti da una categoria e filtra i prodotti non disponibili da quella risposta. Ora l'applicazione visualizza 23 prodotti. In teoria, sarebbe anche possibile una pagina con zero prodotti!
Occasionalmente dovrai eseguire uno script che ripulisca i riferimenti penzolanti, dopo ogni modifica rilevante o ad intervalli regolari. Si noti che tali script sono piuttosto costosi perché devono richiedere ogni prodotto / categoria dal database di supporto / microservizio per vedere se esiste ancora.
Questo dovrebbe essere ovvio, ma per chiarezza: non riutilizzare gli ID. Gli ID in stile autoincremento possono o meno andare bene. I GUID o gli hash offrono maggiore flessibilità, ad esempio potendo assegnare un ID prima che l'elemento venga inserito in un database.
Esempio: ordini simultanei
Ora invece considera una relazione prodotto - ordine. Cosa succede a un ordine se un prodotto viene eliminato o modificato? Ok, possiamo semplicemente copiare i dati rilevanti del prodotto nella voce dell'ordine per tenerli disponibili - scambiando spazio su disco per semplicità. Ma cosa succede se il prezzo del prodotto cambia o il prodotto diventa non disponibile poco prima che venga effettuato un ordine per quel prodotto? In un sistema distribuito, gli effetti richiedono tempo per propagarsi e l'ordine probabilmente passerà attraverso dati obsoleti.
Ancora una volta, come affrontarlo dipende dalle esigenze della tua azienda. Forse l'ordine obsoleto è accettabile e puoi successivamente annullare l'ordine se non può essere eseguito.
Ma forse non è un'opzione, ad es. Per impostazioni altamente concorrenti. Considera 3000 persone che si affrettano ad acquistare i biglietti per i concerti entro i primi 10 secondi e supponiamo che un cambiamento nella disponibilità richieda 10ms per propagarsi. Qual è la probabilità di vendere l'ultimo biglietto a più persone? Dipende da come vengono gestite quelle collisioni, ma utilizzando una distribuzione di Poisson con λ = 3000 / (10s / 10ms) = 3abbiamo una P(k > 1) = 1 - P(k = 0) - P(k = 1) = 80%possibilità di collisione per intervallo di 10 ms. Se la vendita e la successiva cancellazione della maggior parte dei tuoi ordini è possibile senza commettere frodi, potresti condurre a un'interessante conversazione con il tuo ufficio legale.
Pragmatismo significa scegliere le migliori caratteristiche.
La buona notizia è che non è necessario passare a un modello di database distribuito, se non diversamente richiesto. Nessuno revocherà la tua iscrizione al Microservice Club se non esegui i microservizi "correttamente", perché non esiste un club del genere - e non esiste un vero modo per creare microservizi.
Il pragmatismo vince ogni volta, quindi mescola e abbina vari approcci mentre risolvono il tuo problema. Ciò potrebbe anche significare microservizi con un database centralizzato. Davvero, non passare attraverso il dolore dei database distribuiti se non è necessario.
È possibile ridimensionare senza microservizi.
I microservizi hanno due vantaggi principali:
- Il vantaggio organizzativo che possono essere sviluppati e distribuiti in modo indipendente da team separati (che a sua volta richiede che i servizi offrano un'interfaccia stabile).
- Il vantaggio operativo che ogni microservizio può essere ridimensionato in modo indipendente .
Se non è richiesto il ridimensionamento indipendente, i microservizi sono molto meno interessanti.
Un server di database è già un tipo di servizio che è possibile ridimensionare (in qualche modo) in modo indipendente, ad esempio aggiungendo repliche di lettura. Lei menziona le procedure memorizzate. La loro riduzione potrebbe avere un effetto così grande che qualsiasi altra discussione sulla scalabilità è controversa.
Ed è perfettamente possibile avere un monolite scalabile che include tutti i servizi come librerie. È quindi possibile ridimensionare avviando più istanze del monolito, che ovviamente richiede che ogni istanza sia apolide.
Questo tende a funzionare bene fino a quando il monolite è troppo grande per essere ragionevolmente distribuito, o se alcuni servizi hanno requisiti di risorse speciali in modo che tu possa voler ridimensionarli in modo indipendente. I domini problematici che coinvolgono risorse extra potrebbero non coinvolgere un modello di dati separato.
Hai un solido business case?
Sei a conoscenza delle esigenze aziendali della tua organizzazione e puoi quindi creare un argomento per un'architettura di database per microservizio, basata su un'analisi:
- che è richiesta una certa scala e che questa architettura è l'approccio più conveniente per ottenere tale scalabilità, tenendo conto del maggiore sforzo di sviluppo per tale installazione e soluzioni alternative; e
- che i requisiti aziendali consentano di allentare le garanzie ACID pertinenti, senza comportare vari problemi come quelli discussi sopra.
Al contrario, se non sei in grado di dimostrarlo, in particolare se l'attuale progettazione del database è in grado di supportare una scala sufficiente per il futuro (come sembrano credere i tuoi colleghi), allora hai anche la tua risposta.
C'è anche un grande componente YAGNI per la scalabilità. Di fronte all'incertezza, si tratta di una decisione aziendale strategica sulla costruzione della scalabilità ora (costi totali inferiori, ma comporta costi opportunità e potrebbe non essere necessario) rispetto a rinviare alcuni lavori sulla scalabilità (costi totali più elevati se necessario, ma si ha una migliore idea della scala reale). Questa non è principalmente una decisione tecnica.