Предположим, у вас есть приложение, разработанное на Node.js (или любой другой платформе). Это приложение подключается к базе данных MongoDB (NoSQL) для хранения оценок книг (количество звезд и комментарий). Допустим, у вас также есть другое приложение, разработанное на Java (или Python, C#, TypeScript… чем угодно). Это приложение подключается к базе данных MariaDB (SQL, реляционная) для управления каталогом книг (название, год публикации, количество страниц).
Вам предлагается создать отчет, который отображает название и информацию об оценке каждой книги. Обратите внимание, что в базе данных MongoDB не содержится название книг, а в реляционной базе данных нет оценок. Нам нужно объединить данные, созданные NoSQL-приложением, с данными, созданными 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
Этот подход работает. Однако объединение данных – это работа для базы данных. Они созданы для таких операций с данными. Кроме того, с этим подходом SQL-приложение больше не является только SQL-приложением; оно становится полиглоттом базы данных, что увеличивает сложность и усложняет поддержку.
С помощью прокси-сервера базы данных типа MaxScale вы можете объединить эти данные на уровне базы данных, используя лучший язык для данных — SQL. Ваше SQL-приложение не нужно становиться полиглоттом.
Несмотря на то что это требует дополнительного элемента в инфраструктуре, вы также получаете все возможности, которые предлагает прокси-сервер базы данных. Такие вещи, как автоматическое отказоустойчивое, прозрачное маскирование данных, изоляция топологии, кэши, фильтры безопасности и многое другое.
MaxScale — это мощный, интеллектуальный прокси-сервер базы данных, который понимает как SQL, так и NoSQL. Он также понимает Kafka (для CDC или ввода данных), но это тема для другого случая. Короче говоря, с MaxScale вы можете подключить свое приложение NoSQL к полностью совместимой с ACID реляционной базе данных и хранить данные прямо там рядом с таблицами, которые используют другие приложения SQL.
MaxScale позволяет приложению SQL использовать данные NoSQL.
Давайте попробуем этот последний подход в быстром и легком для понимания эксперименте с MaxScale. Вам потребуется следующее установлено на вашем компьютере:
- Docker
- The
mariadb-shell
инструмент - The
mongosh
инструмент
Настройка базы данных MariaDB
С помощью обычного текстового редактора создайте новый файл и сохраните его под названием docker-compose.yml. Файл должен содержать следующее:
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!
Это файл Docker Compose. Он описывает набор сервисов, которые должны быть созданы Docker. Мы создаем два сервиса (или контейнеров) — сервер базы данных MariaDB и прокси-сервер базы данных MaxScale. Они будут работать локально на вашем компьютере, но в производственных средах обычно их развертывают на отдельных физических машинах. Имейте в виду, что эти образы Docker не подходят для производства! Они предназначены для быстрых демонстраций и тестов. Вы можете найти исходный код этих образов на GitHub. Для официальных образов Docker от MariaDB перейдите на страницу MariaDB на Docker Hub.
Предыдущий файл Docker Compose настраивает сервер базы данных MariaDB с базой данных (или схемой; они являются синонимами в MariaDB) под названием demo
. Также создается пользователь с именем user
с паролем Password123!
. Этому пользователю предоставлены соответствующие привилегии на базу данных demo
. Есть дополнительный пользователь с именем maxscale_user
и паролем MaxScalePassword123!
. Это пользователь, который будет использоваться прокси-сервером базы данных MaxScale для подключения к базе данных MariaDB.
Файл Docker Compose также настраивает прокси-сервер базы данных, отключая HTTPS (не делайте этого в производственной среде!), размещая набор портов (подробнее об этом через мгновение), и настраивая пользователя базы данных и расположение прокси-сервера MariaDB базы данных (обычно IP-адрес, но здесь мы можем использовать имя контейнера, ранее определенного в файле Docker). Последняя строка создает слушатель NoSQL, который мы будем использовать для подключения как клиент MongoDB на стандартном порту (27017).
Чтобы запустить сервисы (контейнеры) с помощью командной строки, перейдите в каталог, в котором вы сохранили файл Docker Compose, и выполните следующее:
docker compose up -d
После загрузки всего программного обеспечения и запуска контейнеров у вас будет база данных MariaDB и прокси MaxScale, обе предварительно настроенные для этого эксперимента.
Создание таблицы SQL в MariaDB
Давайте подключимся к реляционной базе данных. В командной строке выполните следующее:
mariadb-shell --dsn mariadb://user:'Password123!'@127.0.0.1
Проверьте, видите ли вы базу данных demo
:
show databases;
Перейдите в базу данных demo
:
use demo;
Подключение к базе данных с помощью MariaDB Shell.
Создайте таблицу books
:
CREATE TABLE books(
isbn VARCHAR(20) PRIMARY KEY,
title VARCHAR(256),
year INT
);
Вставьте некоторые данные. Я собираюсь использовать клише вставки своих книг:
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);
Проверьте, что книги сохранены в базе данных, выполнив:
SELECT * FROM books;
Вставка данных с помощью MariaDB Shell.
Создание JSON-коллекции в MariaDB
Мы еще не установили MongoDB, но мы можем использовать клиент MongoDB (или приложение) для подключения и создания коллекций и документов, как если бы мы использовали MongoDB, за исключением того, что данные хранятся в мощной, полностью соответствующей ACID и масштабируемой реляционной базе данных. Давайте попробуем это!
В командной строке используйте инструмент MongoDB shell для подключения к MongoDB… подождите… на самом деле это база данных MariaDB! Выполните следующее:
mongosh
По умолчанию этот инструмент пытается подключиться к серверу MongoDB (который, опять же, оказывается MariaDB в этот раз) на вашем локальном компьютере (127.0.0.1) с использованием порта по умолчанию (20017). Если все пройдет успешно, вы должны увидеть базу данных demo
в списке при выполнении следующей команды:
show databases
Перейдите в базу данных demo
:
use demo
Подключение к MariaDB с помощью Mongo Shell.
Мы подключены к реляционной базе данных из нереляционного клиента! Давайте создадим коллекцию ratings
и вставим в нее некоторую информацию:
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"
}
])
Проверьте, что рейтинги сохранены в базе данных:
db.ratings.find()
Запрос к базе данных MariaDB с использованием Mongo Shell.
Использование функций JSON в MariaDB
На данный момент у нас есть одна база данных, которая снаружи выглядит как NoSQL (MongoDB) база данных и реляционная (MariaDB) база данных. Мы можем подключиться к той же базе данных и записывать и читать данные из клиентов MongoDB и SQL. Все данные хранятся в MariaDB, поэтому мы можем использовать SQL для объединения данных из клиентов MongoDB или приложений с данными из клиентов MariaDB или приложений. Давайте исследуем, как MaxScale использует MariaDB для хранения данных MongoDB (коллекций и документов).
Подключитесь к базе данных с помощью SQL клиента, такого как mariadb-shell
, и покажите таблицы в демо схеме:
show tables in demo;
Вы должны увидеть как таблицу books
, так и таблицу ratings
. ratings
была создана как коллекция MongoDB. MaxScale перевел команды, отправленные из клиента MongoDB, и создал таблицу для хранения данных в таблице. Давайте посмотрим на структуру этой таблицы:
describe demo.ratings;
A NoSQL collection is stored as a MariaDB relational table.
Таблица ratings
содержит две колонки:
id
: идентификатор объекта.doc
: документ в формате JSON.
Если мы проверим содержимое таблицы, мы увидим, что вся информация о рейтингах хранится в колонке doc
в формате JSON:
SELECT doc FROM demo.ratings \G
Документы NoSQL хранятся в базе данных MariaDB.
Вернемся к нашей изначальной цели — показать названия книг вместе с информацией о рейтинге. Следующее не является правдой, но давайте на мгновение предположим, что таблица ratings
— это обычная таблица с колонками stars
и comment
. Если бы это было так, объединение этой таблицы с таблицей books
было бы легко, и наша работа была бы завершена:
/* this doesn’t work */
SELECT b.title, r.stars, r.comment
FROM ratings r
JOIN books b USING(isbn)
Вернемся к действительности. Нам нужно преобразовать колонку doc
фактической таблицы ratings
в реляционное выражение, которое можно использовать как новую таблицу в запросе. Что-то вроде этого:
/* 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)
Это что-то — функция JSON_TABLE
. MariaDB включает в себя обширный набор функций JSON для манипуляции строками JSON. Мы будем использовать функцию JSON_TABLE
, чтобы преобразовать колонку doc
в реляционную форму, которую мы можем использовать для выполнения SQL-соединений. Общая синтаксис функции JSON_TABLE
следующий:
JSON_TABLE(json_document, context_path COLUMNS (
column_definition_1,
column_definition_2,
...
)
) [AS] the_new_relational_table
Где:
json_document
: строка или выражение, возвращающее используемые JSON-документы.context_path
: выражение JSON Path, определяющее узлы, которые будут использоваться в качестве источника строк.
А определения столбцов (column_definition_1
, column_definition_2
, и т.д…) имеют следующий синтаксис:
new_column_name sql_type PATH path_in_the_json_doc [on_empty] [on_error]
Объединив эти знания, наш SQL-запрос будет выглядеть следующим образом:
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);
Объединение NoSQL и SQL данных в одном SQL-запросе.
Мы могли бы использовать значение ISBN в качестве MongoDB ObjectID и, следовательно, в качестве столбца id
в таблице ratings
, но я оставлю это вам в качестве упражнения (подсказка: используйте _id
вместо isbn
при вставке данных с помощью клиента или приложения MongoDB).
A Word on Scalability
Есть заблуждение, что реляционные базы данных не масштабируются горизонтально (добавлением большего количества узлов), в то время как NoSQL базы данных это делают. Но реляционные базы данных масштабируются без потери свойств ACID. MariaDB имеет несколько хранилищ, предназначенных для разных нагрузок. Например, вы можете масштабировать базу данных MariaDB, внедрив шардирование данных с помощью Spider. Вы также можете использовать различные хранилища для управления разными нагрузками на основе таблицы. В одном SQL-запросе возможны соединения между хранилищами.
Объединение нескольких хранилищ в одной логической базе данных MariaDB.
Еще один более современный вариант – распределенный SQL с использованием MariaDB Xpand. Распределенная SQL-база данных выглядит как единый логический реляционный сервер для приложений благодаря прозрачному разбиению на фрагменты. Она использует архитектуру без общих ресурсов, которая масштабируется как для чтения, так и для записи.
A distributed SQL database deployment.
Заключение
Наша работа здесь завершена! Теперь ваши системы могут иметь согласованный масштабируемый 360-градусный обзор ваших данных независимо от того, были ли они созданы приложениями SQL или NoSQL. Меньше необходимости перемещать ваши приложения из NoSQL в SQL или делать приложения SQL полиглотом для баз данных. Если вы хотите узнать больше о других функциях MaxScale, смотрите это видео или посетите документацию.
Source:
https://dzone.com/articles/mixing-sql-and-nosql-with-mariadb-and-mongodb