MySQL – це найкраща NoSQL-система

При розгляді сценаріїв використання NoSQL, таких як зберігання пар ключ-значення, виявляється, що MySQL більш краща з точки зору продуктивності, легкості використання і стабільності. MySQL – це грунтовна система з великою кількістю онлайн-матеріалів, що охоплюють всі теми від основних операцій та розбору помилок до реплікації і різних патернів використання. Це дає MySQL перевага перед більш молодими NoSQL-системами, у яких немає такого досвіду.

За останні роки NoSQL-системи стали панівним напрямком. Багато розробники вбачають у NoSQL-системах, таких як MongoDB, Cassandra, Redis або Hadoop, оптимальний варіант для побудови своїх додатків, вважаючи їх єдиною родиною продуктів, яка знецінює старі SQL-системи.

Найчастіше, в основі рішення про використання бази даних NoSQL лежить рекламна галас або помилкове переконання, що реляційні бази даних не можуть забезпечити таку ж продуктивність, як бази даних NoSQL. Коли доходить до вибору бази даних, інженери часто випускають з уваги експлуатаційні витрати, а також міркування стабільності і зрілості технології. Щоб дізнатися більше про обмеження і вади різних NoSQL (SQL) систем, зверніть увагу на серію статей проекту Jepsen, опубліковану на Aphyr.com.

У цій статті ми пояснимо, чому, на нашу думку, використовувати MySQL для зберігання пар ключ-значення краще, ніж більшість спеціалізованих NoSQL-систем, а також надамо інструкції для використання MySQL.

Визначення сайтів Wix
Коли хтось натискає посилання на сайті Wix, його браузер посилає на сервер Wix HTTP-запит з адресою сайту. Так відбувається і з преміум-сайтом Wix, мають власний домен (напр. domain.com), і з безкоштовним сайтом на субдомені Wix (напр. user.wix.com/site). Сервер повинен розпізнати найпопулярніший сайт з адресою сайту, виконуючи пошук типу " ключ-значення для пари URL-сайт. У подальшому обговоренні ми будемо позначати URL як «шлях» (route).

Таблиця routes використовується, щоб перетворити адресу сайту в об'єкт site. Оскільки для потрапляння на сайт можуть використовуватися різні шляхи, тут має місце відношення «багато до одного». Коли сайт знайдено, програма завантажує його, щоб працювати з ним. Об'єкт site, в свою чергу, має складну структуру, яка включає два списку дочірніх об'єктів – різні сервіси, що використовуються сайтом. Нижче наведена приблизна модель наших об'єктів. Тут ми припускаємо, що використовується стандартна база даних SQL з нормалізованої структурою:



При оновленні сайту з традиційною нормалізованої моделлю нам необхідно використовувати транзакцію для оновлення множинних таблиць, щоб забезпечити цілісність даних (зверніть увагу, що транзакція використовує блокування на рівні бази даних, що запобігає одночасну запис, а іноді і читання з задіяних таблиць). Продовжуючи працювати з такою моделлю, ми, ймовірно, дійдемо до ключа типу SERIAL в кожній таблиці, зовнішніх ключів та індексу в полі URL таблиці routes.

Однак, моделювання даних на основі нормалізованої схеми загрожує низкою ускладнень:

• блокування обмежують доступ до таблиці, тому при великих обсягах даних це може обмежити нашу продуктивність;
• читання об'єкта вимагає або декількох SQL запитів (4 в нашому випадку) або використання JOIN – і це теж впливає на час затримки;
• ключі з атрибутом SERIAL вимагають блокування, що знову обмежує продуктивність запису.

Ці проблеми обмежують пропускну здатність і розпаралелювання запитів, які нам здатна забезпечити MySQL (або будь-яка інша SQL-система). З-за цих слабких місць, а також в силу того факту, що мова йде по суті про парі ключ-значення, багато розробники воліють шукати NoSQL-рішення, яке забезпечує кращу продуктивність і розпаралелювання, навіть ціною стабільності, цілісності і доступності.

Ми в Wix виявили, що MySQL, якщо її творчо використовувати в якості сховища пар ключ-значення, що може працювати краще, ніж MySQL з нормалізованої моделлю даних наведеної вище), а також краще, ніж більшість NoSQL-систем. Наша нинішня система забезпечує такі параметри масштабування, пропускної здатності, розпаралелювання запитів, часу затримки, які зробили б честь будь-NoSQL-системі. Ось деякі дані нашої системи:

• активна установка на три дата-центру (active-active-active);
• пропускна здатність близько 200 000 RPM;
• таблиця routes має обсяг близько 100 000 000 записів, 10 ГБ дискового простору;
• таблиця sites має близько 100 000 000 записів, 200 ГБ дискового простору;
• середня затримка читання – 1,0-1,5 мілісекунди (фактично, 0,2-0,3 мс. в одному дата-центрі).

Зауважте, затримка порядку 1,0 мс. вважається вражаючим показником в більшості систем, побудованих на парі ключ-значення, включаючи як хмарні системи, так і системи з відкритим кодом. І ми досягли цього, використовуючи MySQL (найпростішу, як прийнято вважати, SQL-систему).

Ось схема, яку ми використовуємо:



CREATE TABLE `routes` (
`route` varchar(255) NOT NULL,
`site_id` varchar(50) NOT NULL,
`last_update_date` bigint NOT NULL,
PRIMARY KEY (`key`),
KEY (`site_id`)
)

CREATE TABLE `sites` (
`site_id` varchar(50) NOT NULL,
`owner_id` varchar(50) NOT NULL,
`schema_version` varchar(10) NOT NULL DEFAULT '1.0',
`site_data` text NOT NULL,
`last_update_date` bigint NOT NULL,
PRIMARY KEY (`site_id`)
) /*ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=16*/;

Всі поля, які не використовуються в якості критеріїв запиту, були згорнуті в єдине поле типу blob (текстове поле site_data). Воно включає таблиці sub-obj, а також будь-які поля самого об'єкта table. Зауважте, ми не використовуємо ключів типу SERIAL, замість цього ми використовуємо поле типу VARCHAR(50), яке містить створені користувачем змінні GUID (про це докладніше в наступному розділі).

Нижче наведено використовуваний нами запит, у нього висока пропускна здатність і низький час затримки:

select * from sites where site_id = (
select site_id from routes where route = ?
)

Тут спочатку виконується запит до таблиці routes по унікальному індексу, запит повинен повернути тільки одне значення. Потім ми переглядаємо сайти по первинному ключу, знову шукаємо одне значення. Вкладений синтаксис дозволяє обробити обидва SQL-запиту за одне звернення до бази даних.

Результат, показаний вище, вимагає приблизно 1 мс. послідовної роботи в умовах високого трафіку і високої частоти оновлення. Оновлення полутранзакционные, навіть без використання транзакцій. Це стає можливим завдяки тому, що ми вводимо весь сайт однією командою INSERT і, поки ми не введемо дані в routes, запити не будуть його виявляти. Тобто, коли ми вводимо спочатку дані про сайт, а потім про шляхи, які ми впевнені в цілісності своїх даних, навіть у прикордонній ситуації, поки наші дані в таблиці sites не пов'язані.

Інструкції по використанню MySQL в якості NoSQL-системи
Використовуючи досвід, набутий в описаному вище прикладі (і інших подібних випадках з практики Wix), ми розробили короткий список рекомендацій для використання MySQL в якості NoSQL системи.

Головне, що слід пам'ятати при використанні MySQL в якості NoSQL-системи – це уникати блокувань на рівні бази і складних запитів.

• Не використовуйте транзакції, які передбачають блокування. Замість цього, використовуйте транзакції в додатку;
• не використовуйте ключі типу SERIAL. Такі ключі тягнуть за собою блокування і ускладнюють конфігурацію виду active-active;
• використовуйте унікальні ключі, створені клієнтами. Ми використовуємо GUID.

Оптимізуючи структуру для читання, зверніть увагу ще на кілька додаткових рекомендацій:

• не проводите нормалізацію;
• якщо є поле – воно має індексуватися. Якщо поле індексу не потрібно, збережіть його в одному полі типу BLOB / TEXT (як JSON, XML);
• не використовуйте зовнішні ключі;
• створюйте вашу структуру так, щоб за запитом можна було прочитати окремий ряд;
• не використовуйте оператор ALTER TABLE. Ці команди тягнуть за собою блокування і періоди тимчасової непрацездатності. Замість цього, використовуйте перенесення даних Live Migration.

При запиті даних:

• шукайте записи по первинному ключу або по індексу;
• не користуйтеся JOIN;
• не користуйтеся функціями агрегування;
• запускайте функції перевірки (BI, дослідження даних) на репліках, а не на головній базі.
Ми плануємо написати ще одну статтю, де розповімо детальніше про перенесення даних Live Migrations і транзакції через додаток.

Ви можете думати по-новому
Мабуть, це найважливіший висновок з цієї статті. Це здорово – використовувати MySQL в якості NoSQL-системи, тобто не так, як вона була спроектована. Як показано в цій статті, прикладом служить використання MySQL для роботи з парами ключ-значення замість спеціально спроектованих для цього NoSQL-систем. Ми в Wix вибрали MySQL для роботи з парами ключ-значення (і не тільки), оскільки її легко використовувати, їй легко керувати, і це відмінна екосистема. В якості бонусу, вона забезпечує показники затримки, пропускної здатності та розпаралелювання, чи не перевершують більшість NoSQL-систем.

Головний архітектор програмного забезпечення конструктора створення сайтів Wix
Йоав Абрахами

Оригінал статті: блог інженерів компанії Wix
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.