Immaginiamo di avere un’applicazione sviluppata in Node.js (o qualsiasi altro ambiente). Questa applicazione si connette a un database MongoDB (NoSQL) per memorizzare valutazioni su libri (numero di stelle assegnate e un commento). Supponiamo inoltre di avere un’altra applicazione sviluppata in Java (o Python, C#, TypeScript… qualsiasi cosa). Questa applicazione si connette a un database MariaDB (SQL, relazionale) per gestire un catalogo di libri (titolo, anno di pubblicazione, numero di pagine).
Ti viene chiesto di creare un rapporto che mostri il titolo e le informazioni sul rating per ogni libro. Nota che il database MongoDB non contiene il titolo dei libri, e il database relazionale non contiene le valutazioni. Dobbiamo mescolare dati creati da un’applicazione NoSQL con dati creati da un’applicazione SQL.
A common approach to this is to query both databases independently (using different data sources) and process the data to match by, for example, ISBN (the id of a book) and put the combined information in a new object. This needs to be done in a programming language like Java, TypeScript, C#, Python, or any other imperative programming language that is able to connect to both databases.
A polyglot application
Questo approccio funziona. Tuttavia, unire i dati è un compito per un database. Sono progettati per questo tipo di operazione sui dati. Inoltre, con questo approccio, l’applicazione SQL non è più un’applicazione esclusivamente SQL; diventa un poliglotta di database, e ciò aumenta la complessità, rendendola più difficile da mantenere.
Con un proxy di database come MaxScale, puoi unire questi dati a livello di database utilizzando il miglior linguaggio per i dati — SQL. La tua applicazione SQL non ha bisogno di diventare poliglota.
Anche se questo richiede un elemento aggiuntivo nell’infrastruttura, si ottengono anche tutte le funzionalità che un database proxy ha da offrire. Cose come failover automatico, mascheramento dei dati trasparente, isolamento della topologia, cache, filtri di sicurezza e altro ancora.
MaxScale è un potente proxy di database intelligente che comprende sia SQL che NoSQL. Comprende anche Kafka (per CDC o inserimento dati), ma questo è un argomento per un’altra occasione. In breve, con MaxScale, puoi connettere il tuo applicativo NoSQL a un database relazionale pienamente conforme agli ACID relational database e memorizzare i dati proprio lì accanto alle tabelle che utilizzano altri applicativi SQL.
MaxScale consente a un applicativo SQL di consumare dati NoSQL.
Proviamo quest’ultimo approccio in un esperimento rapido ed intuitivo con MaxScale. Avrai bisogno delle seguenti installazioni sul tuo computer:
Configurazione del Database MariaDB
Usando un editor di testo normale, crea un nuovo file e salvalo con il nome docker-compose.yml. Il file dovrebbe contenere quanto segue:
version: "3.9"
services:
mariadb:
image: alejandrodu/mariadb
environment:
- MARIADB_CREATE_DATABASE=demo
- MARIADB_CREATE_USER=user:Password123!
- MARIADB_CREATE_MAXSCALE_USER=maxscale_user:MaxScalePassword123!
maxscale:
image: alejandrodu/mariadb-maxscale
command: --admin_host 0.0.0.0 --admin_secure_gui false
ports:
- "3306:4000"
- "27017:27017"
- "8989:8989"
environment:
- MAXSCALE_USER=maxscale_user:MaxScalePassword123!
- MARIADB_HOST_1=mariadb 3306
- MAXSCALE_CREATE_NOSQL_LISTENER=user:Password123!
Questo è un file Docker Compose. Descrive un insieme di servizi da creare con Docker. Stiamo creando due servizi (o contenitori) — un server di database MariaDB e un proxy di database MaxScale. Saranno in esecuzione localmente sul tuo computer, ma in ambienti di produzione, è comune distribuirli su macchine fisiche separate. Tieni presente che queste immagini Docker non sono adatte per la produzione! Sono pensate per essere adatte per rapide demo e test. Puoi trovare il codice sorgente per queste immagini su GitHub. Per le immagini Docker ufficiali da MariaDB, vai alla pagina MariaDB su Docker Hub.
Il file Docker Compose precedente configura un server di database MariaDB con un database (o schema; sono sinonimi in MariaDB) chiamato demo
. Viene inoltre creato un nome utente user
con la password Password123!
. Questo utente dispone dei privilegi adeguati sul database demo
. C’è un altro utente con nome maxscale_user
e password MaxScalePassword123!
. Questo è l’utente che il proxy database MaxScale utilizzerà per connettersi al database MariaDB.
Il file Docker Compose configura anche il proxy database disabilitando HTTPS (non farlo in produzione!), esponendo un insieme di porte (più su questo tra un momento), e configurando l’utente del database e la posizione del proxy MariaDB (di solito un indirizzo IP, ma qui possiamo utilizzare il nome del contenitore precedentemente definito nel file Docker). L’ultima riga crea un listener NoSQL che useremo per connetterci come client MongoDB sulla porta predefinita (27017).
Per avviare i servizi (contenitori) usando la riga di comando, spostati nella directory in cui hai salvato il file Docker Compose e esegui quanto segue:
docker compose up -d
Dopo aver scaricato tutto il software e avviato i contenitori, avrai un database MariaDB e un proxy MaxScale, entrambi preconfigurati per questo esperimento.
Creazione di una Tabella SQL in MariaDB
Connettiamoci al database relazionale. Nella riga di comando, esegui quanto segue:
mariadb-shell --dsn mariadb://user:'Password123!'@127.0.0.1
Verifica che sia visibile il database demo
:
show databases;
Passa al database demo
:
use demo;
Connessione a un database con MariaDB Shell.
Crea la tabella books
:
CREATE TABLE books(
isbn VARCHAR(20) PRIMARY KEY,
title VARCHAR(256),
year INT
);
Inserisci alcuni dati. Userò il cliché di inserire i miei libri:
INSERT INTO books(title, isbn, year)
VALUES
("Vaadin 7 UI Design By Example", "978-1-78216-226-1", 2013),
("Data-Centric Applications with Vaadin 8", "978-1-78328-884-7", 2018),
("Practical Vaadin", "978-1-4842-7178-0", 2021);
Verifica che i libri siano memorizzati nel database eseguendo:
SELECT * FROM books;
Inserimento dei dati con MariaDB Shell.
Creazione di una Collection JSON in MariaDB
Non abbiamo ancora installato MongoDB, eppure possiamo utilizzare un client MongoDB (o applicazione) per connetterci e creare collezioni e documenti come se stessimo usando MongoDB, tranne per il fatto che i dati sono memorizzati in un potente database relazionale completamente conforme ACID e scalabile. Proviamolo!
Nella riga di comando, usa lo strumento shell MongoDB per connetterti al MongoDB… aspetta… è in realtà il database MariaDB! Esegui quanto segue:
mongosh
Per impostazione predefinita, questo strumento cerca di connettersi a un server MongoDB (che, ancora una volta, si rivela essere MariaDB questa volta) in esecuzione sul tuo computer locale (127.0.0.1) utilizzando la porta predefinita (20017). Se tutto va bene, dovresti essere in grado di vedere il database demo
elencato quando esegui il seguente comando:
show databases
Passa al database demo
:
use demo
Connessione a MariaDB utilizzando Mongo Shell.
Siamo connessi a un database relazionale da un client non relazionale! Creiamo la raccolta ratings
e inseriamo alcuni dati in essa:
db.ratings.insertMany([
{
"isbn": "978-1-78216-226-1",
"starts": 5,
"comment": "A good resource for beginners who want to learn Vaadin"
},
{
"isbn": "978-1-78328-884-7",
"starts": 4,
"comment": "Explains Vaadin in the context of other Java technologies"
},
{
"isbn": "978-1-4842-7178-0",
"starts": 5,
"comment": "The best resource to learn web development with Java and Vaadin"
}
])
Verifica che le valutazioni siano persistenti nel database:
db.ratings.find()
Consultazione di un database MariaDB utilizzando Mongo Shell.
Utilizzo delle Funzioni JSON in MariaDB
A questo punto, abbiamo un unico database che, dall’esterno, sembra un database NoSQL (MongoDB) e un database relazionale (MariaDB). Siamo in grado di connetterci allo stesso database e scrivere e leggere dati da client MongoDB e client SQL. Tutti i dati sono memorizzati in MariaDB, quindi possiamo utilizzare SQL per unire dati da client MongoDB o applicazioni con dati da client MariaDB o applicazioni. Esploriamo come MaxScale utilizza MariaDB per memorizzare dati MongoDB (raccolte e documenti).
Connettiti al database utilizzando un client SQL come mariadb-shell
e visualizza le tabelle nello schema dimostrativo:
show tables in demo;
Dovresti vedere sia la tabella books
che la tabella ratings
elencate. ratings
è stata creata come una raccolta MongoDB. MaxScale ha tradotto i comandi inviati dal client MongoDB e ha creato una tabella per memorizzare i dati in una tabella. Diamo un’occhiata alla struttura di questa tabella:
describe demo.ratings;
A NoSQL collection is stored as a MariaDB relational table.
La tabella ratings
contiene due colonne:
id
: l’ID oggetto.doc
: il documento in formato JSON.
Se controlliamo il contenuto della tabella, vedremo che tutti i dati sulle valutazioni sono memorizzati nella colonna doc
in formato JSON:
SELECT doc FROM demo.ratings \G
I documenti NoSQL sono memorizzati in un database MariaDB.
Torniamo al nostro obiettivo originale: mostrare i titoli dei libri con le informazioni sulle valutazioni. Il seguente scenario non è quello reale, ma supponiamo per un momento che la tabella ratings
sia una tabella regolare con le colonne stars
e comment
. Se fosse così, unire questa tabella con la tabella books
sarebbe facile e il nostro lavoro sarebbe fatto:
/* this doesn’t work */
SELECT b.title, r.stars, r.comment
FROM ratings r
JOIN books b USING(isbn)
Torniamo alla realtà. Dobbiamo convertire la colonna doc
della tabella effettiva ratings
in un’espressione relazionale che possa essere utilizzata come nuova tabella nella query. Qualcosa di simile a questo:
/* this still doesn’t work */
SELECT b.title, r.stars, r.comment
FROM ratings rt
JOIN ...something to convert rt.doc to a table... AS r
JOIN books b USING(isbn)
Quel qualcosa è la funzione JSON_TABLE
. MariaDB include un’ampia gamma di funzioni JSON per manipolare stringhe JSON. Utilizzeremo la funzione JSON_TABLE
per convertire la colonna doc
in una forma relazionale che possiamo utilizzare per eseguire join SQL. La sintassi generale della funzione JSON_TABLE
è la seguente:
JSON_TABLE(json_document, context_path COLUMNS (
column_definition_1,
column_definition_2,
...
)
) [AS] the_new_relational_table
Dove:
json_document
: una stringa o un’espressione che restituisce i documenti JSON da utilizzare.context_path
: una espressione JSON Path che definisce i nodi da utilizzare come fonte delle righe.
E le definizioni delle colonne (column_definition_1
, column_definition_2
, ecc…) hanno la seguente sintassi:
new_column_name sql_type PATH path_in_the_json_doc [on_empty] [on_error]
Combinando queste conoscenze, la nostra query SQL sarebbe simile alla seguente:
SELECT b.title, r.stars, r.comment
FROM ratings rt
JOIN JSON_TABLE(rt.doc, '$' COLUMNS(
isbn VARCHAR(20) PATH '$.isbn',
stars INT PATH '$.starts',
comment TEXT PATH '$.comment'
)
) AS r
JOIN books b USING(isbn);
Unire dati NoSQL e SQL in una singola query SQL.
Avremmo potuto utilizzare il valore ISBN come ObjectID MongoDB e, di conseguenza, come colonna id
nella tabella ratings
, ma lascerò questo a te come esercizio (suggerimento: usa _id
invece di isbn
quando inserisci dati utilizzando il client o l’app MongoDB).
A Word on Scalability
C’è un’errata concezione che i database relazionali non scalano orizzontalmente (aggiungendo più nodi) mentre i database NoSQL lo fanno. Ma i database relazionali scalano senza sacrificare le proprietà ACID. MariaDB ha più motori di storage adatti a diversi carichi di lavoro. Ad esempio, puoi scalare un database MariaDB implementando il partizionamento dei dati con l’aiuto di Spider. Puoi anche utilizzare una varietà di motori di storage per gestire diversi carichi di lavoro a livello di tabella. Le join tra motori sono possibili in una singola query SQL.
Combinazione di più motori di storage in un singolo database logico MariaDB.
Un’alternativa più moderna è SQL distribuito con MariaDB Xpand. Un database SQL distribuito si presenta come un singolo database relazionale logico agli applicativi attraverso lo sharding trasparente. Adotta un’architettura shared-nothing che si espande sia per la lettura che per la scrittura.
A distributed SQL database deployment.
Conclusione
Il nostro compito qui è terminato! Ora, i vostri sistemi possono avere una visione scalabile 360 gradi dei vostri dati conforme a ACID, indipendentemente dal fatto che siano stati creati da applicazioni SQL o NoSQL. C’è meno necessità di migrare le vostre app da NoSQL a SQL o di rendere le app SQL polyglot di database. Se volete saperne di più su altre caratteristiche di MaxScale, guardate questo video o visitate le documentazioni.
Source:
https://dzone.com/articles/mixing-sql-and-nosql-with-mariadb-and-mongodb