Шардинг та реплікація

(На основі https://ruhighload.com/)

Масштабування баз даних - найскладніше завдання під час росту проекту. 90% всіх зусиль зазвичай припадає саме на роботу, пов'язану з ростом обсягу даних і операцій з ними.
Класична схема роботи програми з базою даних виглядає так:
Один сервер бази даних в якийсь момент перестає справлятися з навантаженням. У цей момент слід застосовувати описані тут техніки масштабування.
Перед тим, як приступати до масштабування, необхідно провести аналіз повільних запитів і переконатися, що сервер MySQL налаштований оптимально.

Cтратегії.
В основі масштабування даних лежить той же принцип, що і в основі масштабування Web додатків. Це поділ даних на групи і виділення їх на окремі сервера. Існує дві основні стратегії - реплікація і шардінг.

Реплікація
Реплікація дозволяє створити повний дублікат бази даних. Так, замість одного сервера у Вас їх буде кілька: Найчастіше використовують схему master-slave:

Реплікація дозволяє використовувати два або більше однакових серверів замість одного. Операцій читання (SELECT) даних часто набагато більше, ніж операцій зміни даних (INSERT/UPDATE). Тому, реплікація дозволяє розвантажити основний сервер за рахунок перенесення операцій читання на слейв.

Робота з програми
У додатку у Вас має бути два з'єднання з базою даних. Одне - для майстра і одне для слейв:

 <?
 $Master = mysql_connect ('10 .10.0.1 ',' root ',' pwd ');
 $Slave = mysql_connect ('10 .10.0.2 ',' root ',' pwd ');
 <Коди>
 $q = mysql_query ( 'INSERT INTO users ....', $Master);
 <Коди>
 $q = mysql_query ( 'SELECT FROM users WHERE ....', $Slave);
          		<Коди>

При виконанні запитів необхідно використовувати відповідне з'єднання.
Реплікація зазвичай підтримується самою СУБД (наприклад, MySQL) і налаштовується незалежно від програми. Слід зазначити, що реплікація сама по собі не дуже зручний механізм масштабування.
Причиною є – порушення синхронізації даних і затримки в копіюванні з майстра на слейв. Зате це відмінний засіб для забезпечення відмовостійкості. Ви завжди можете переключитися на слейв, якщо майстер ламається і навпаки. Найчастіше реплікація використовується спільно з шардінгом саме з міркувань надійності.

Шардінг (sharding)
Шардінг (іноді шардірування) – це інша техніка масштабування роботи з даними. Суть його полягає в поділі бази даних на окремі частини (partition, секціювання) так, щоб кожну з них можна було винести на окремий сервер. Цей процес залежить від структури бази даних і виконується прямо в додатку на відміну від реплікації.

Вертикальний шардінг
Вертикальний шардінг - це виділення таблиці або групи таблиць на окремий сервер. Наприклад, в додатку є такі таблиці:

Таблицю users Ви залишаєте на одному сервері, а таблиці photos і albums переносите на інший. В такому випадку в додатку Вам необхідно буде використовувати відповідне з'єднання для роботи з кожною таблицею:

 <?
 $users_connection = mysql_connect ('10 .10.0.1 ',' root ',' pwd ');
 $photos_connection = mysql_connect ('10 .10.0.2 ',' root ',' pwd ';
  <коди>
 $q = mysql_query ( 'SELECT * FROM users WHERE ...', $users_connection);
  <коди>
 $q = mysql_query ( 'SELECT * FROM photos WHERE ...', $photos_connection);
   <коди>
 $q = mysql_query ( 'SELECT * FROM albums WHERE ...', $photos_connection);

Для кожної таблиці або групи таблиць буде окреме з'єднання. На відміну від реплікації, ми використовуємо різні з'єднання для будь-яких операцій, але з певними таблицями.

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

Припустимо, наш додаток працює з величезною таблицею, яка зберігає фотографії користувачів. Ми підготували два сервера (зазвичай вони називаються шардами) для цієї таблиці.
Для непарних користувачів ми будемо працювати з першим сервером, а для парних – з другим. Таким чином, на кожному з серверів буде тільки частина всіх даних про фотографії користувачів. Це буде виглядати так:

 <?
 # Список з'єднань для таблиці з фотками
 $photo_connections = [
  '1' => '10 .10.0.1 ',
  '2' => '10 .10.0.2 ',
 ]
 $user_id = $ _SESSION [ 'user_id'];
 # Отримання фотографій для користувача $user_i
 $connection_num = $user_id% 2 == 0? 1: 2;
 $connection = mysql_connect ($photo_connections [$connection_num],'root', 'pwd');
 $q = mysql_query ( 'SELECT * FROM photos WHREE user_id ='. Intval ($user_id), $connection);
 # Перед зверненням до таблиці, ми вибираємо потрібне нам з'єднання.

Результат цієї операції $user_id% 2 буде залишком від ділення на 2. Тобто для парних чисел - 0, а для непарних - 1. Будь-яка робота з таблицею photos тепер буде відбуватися тільки після отримання потрібного з'єднання на основі $user_id.
Горизонтальний шардінг – це дуже потужний інструмент масштабування даних. Але в той же час і дуже нетривіальний. Не слід застосовувати техніку шардінга до всіх таблиць.
Правильний підхід - це поетапний процес поділу зростаючих таблиць. Слід замислюватися про горизонтальний шардінг, коли кількість рядків в одній таблиці переходить за межі від кількох десятків мільйонів до сотень мільйонів.

Спільне використання
Шардінг і реплікація часто використовуються спільно. У нашому прикладі, ми могли б використовувати по два сервера на кожен шард таблиці:

Тоді в додатку робота з цією таблицею може виглядати так:

 <?
 # Список з'єднань, для кожного шарда - майстер і слейв
 $photo_connections = [
  '1' => [
  'Master' => '10 .10.0.10 ',
  'Slave' => '10 .10.0.11 ',
 ],
 '2' => [
  'Master' => '10 .10.0.20 ',
  'Slave' => '10 .10.0.21 ',
  ],
 ];
 $user_id = $ _SESSION [ 'user_id'];
 # Читаємо дані з слейв
 $connection_num = $user_id% 2 == 0? 1: 2;
 $connection = mysql_connect ($photo_connections [$connection_num] [ 'slave'], 'root', 'pwd');
 $q = mysql_query ( 'SELECT * FROM photos WHREE user_id ='. Intval ($user_id), $connection);
   <Коди>
 # Зміна даних відбувається на майстрах
  $photo_id = 7;
  $connection_num = $user_id% 2 == 0? 1: 2;
  $connection = mysql_connect ($photo_connections [$connection_num] [ 'master'], 'root', 'pwd');
  $q = mysql_query ( 'UPDATE photos SET views = views + 1 WHREE photo_id ='. Intval ($photo_id), $connection);
 # Читаємо дані з слейв, а записуємо на майстер-сервер/

Така схема часто використовується не для масштабування, а для забезпечення відмовостійкості. Так, при виході з ладу одного з серверів шардена, інший завжди буде запасний.

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