Який найкращий підхід для Sharding таблиць MySQL. Підходи, які я можу придумати, такі:
- Затінення рівня додатка?
- Шардінг на рівні проксі MySQL?
- Центральний сервер пошуку для шардингу?
Чи знаєте ви про якісь цікаві проекти чи інструменти в цій галузі?
Відповіді:
Найкращий підхід для шардінгу таблиць MySQL - не робити цього, якщо це зовсім не уникнути.
Коли ви пишете заявку, ви зазвичай хочете зробити це таким чином, щоб максимізувати швидкість і швидкість розробника. Ви оптимізуєте затримки (час, поки відповідь не буде готова) або пропускну здатність (кількість відповідей на одиницю часу), лише коли це необхідно.
Ви розділяєте, а потім присвоюєте розділи різним хостам (= осколок) лише тоді, коли сума всіх цих розділів більше не вміщується на одному екземплярі сервера бази даних - причиною цього є або запис, або читання.
Випадок запису - це а) частота записів перевантажує ці сервери дисками постійно, або б) відбувається занадто багато записів, щоб реплікація постійно відставала в цій ієрархії реплікації.
Випадок зчитування для шардінгу - це коли розмір даних настільки великий, що робочий набір їх більше не поміщається в пам’ять, і зчитування даних починає потрапляти на диск, а не подаватися з пам'яті більшу частину часу.
Ви робите це лише тоді, коли вам потрібно осколок.
У момент, коли ви осколки, ви платите за це різними способами:
Більша частина вашого SQL більше не є декларативною.
Зазвичай в SQL ви повідомляєте базі даних, які дані ви хочете, і залишаєте за оптимізатором, щоб перетворити цю специфікацію на програму доступу до даних. Це добре, оскільки це гнучко, і тому, що написання цих програм доступу до даних - це нудна робота, яка шкодить швидкості.
У шардованому середовищі ви, мабуть, приєднуєтесь до таблиці на вузлі A проти даних на вузлі B, або у вас є таблиця, більша за вузол, на вузлах A і B і приєднуєте дані з неї до даних, що знаходяться на вузлах B і C. Ви починаєте писати резолюції об'єднання на базі додатків на основі хешу вручну, щоб вирішити це (або ви заново винаходите кластер MySQL), тобто ви отримуєте багато SQL, який більше не є декларативним, але виражає функціональність SQL процедурним способом (наприклад, ви використовуєте оператори SELECT у циклах).
У вас виникає велика затримка мережі.
Зазвичай запит SQL може бути вирішений локально, і оптимізатор знає про витрати, пов'язані з доступом до локального диска, і вирішує запит таким чином, щоб мінімізувати витрати на це.
У шардованому середовищі запити вирішуються або шляхом запуску доступу до ключа та значення через мережу до кількох вузлів (сподіваємось, із пакетним доступом до ключів, а не окремими пошуками ключів за туди і назад), або шляхом переміщення частин WHEREречення далі до вузлів, де вони можуть бути застосованим (що називається "зниженням стану"), або тим і іншим.
Але навіть у найкращих випадках це передбачає набагато більше мережевих поїздок, ніж місцева ситуація, і це складніше. Тим більше, що оптимізатор MySQL взагалі нічого не знає про затримку мережі (добре, кластер MySQL поволі стає кращим, але для ванільного MySQL поза кластером це все ще правда).
Ви втрачаєте багато виразної сили SQL.
Гаразд, це, мабуть, менш важливо, але обмеження зовнішнього ключа та інші механізми SQL для цілісності даних не здатні охопити декілька осколків.
MySQL не має API, який дозволяє асинхронні запити, що працюють.
Коли дані одного типу містяться на кількох вузлах (наприклад, дані користувачів на вузлах A, B і C), часто потрібно вирішувати горизонтальні запити щодо всіх цих вузлів ("Знайти всі облікові записи користувачів, які не були ввійшли в систему протягом 90 днів або більше"). Час доступу до даних лінійно зростає із числом вузлів, якщо паралельно не можна запитувати декілька вузлів і результати агрегувати в міру надходження ("Зменшити карту").
Передумовою цього є API асинхронного зв'язку, який не існує для MySQL у належній робочій формі. Альтернативою є велика кількість розгалужень та зв’язків у дитячих процесах, які відвідують світ смоктання на сезонному абонементі.
Після того, як ви почнете робити шардування, структура даних та топологія мережі стають видимими як показники продуктивності вашого додатка. Для того, щоб працювати досить добре, ваш додаток повинен знати про ці речі, а це означає, що насправді має сенс лише посилення рівня додатків.
Питання полягає ще більше в тому, чи ви хочете здійснити автоматичне оббивання (наприклад, визначаючи, який рядок входить до якого вузла, хешуючи первинні ключі), чи ви хочете функціонально розділити вручну ("Таблиці, пов’язані з історією користувача xyz, переходять до цього master, тоді як таблиці, пов'язані з abc та def, переходять до цього master ").
Функціональне шардінг має ту перевагу, що, якщо все зробити правильно, воно більшість разів невидиме для більшості розробників, оскільки всі таблиці, пов’язані з їх історією користувачів, будуть доступні локально. Це дозволяє їм як і раніше користуватися декларативним SQL, а також матиме менше затримок мережі, оскільки кількість міжмережевих передач зведена до мінімуму.
Функціональне затінення має той недолік, що не дозволяє жодній окремій таблиці бути більше одного екземпляра, і воно вимагає ручної уваги дизайнера.
Функціональне шардінг має ту перевагу, що його порівняно легко зробити для існуючої кодової бази з низкою змін, які не надто великі. http://Booking.com робив це неодноразово протягом останніх років, і це добре працювало для них.
Сказавши все це, дивлячись на ваше запитання, я впевнений, що ви ставите неправильні запитання, або я абсолютно неправильно розумію вашу заяву про проблему.
Заточення рівня програм: dbShards - це єдиний відомий мені продукт, який робить "шардування з урахуванням додатків". На веб-сайті є кілька хороших статей. Тільки за визначенням, шардування з урахуванням додатків буде більш ефективним. Якщо додаток точно знає, куди звертатися з транзакцією, не шукаючи її або перенаправляючи через проксі, це само по собі буде швидше. І швидкість часто є однією з головних проблем, якщо не єдиною проблемою, коли хтось шукає шардингу.
Деякі люди "осколюють" за допомогою проксі, але на мої очі це перемагає мету шардування. Ви просто використовуєте інший сервер, щоб повідомити про свої транзакції, де знайти дані або де їх зберігати. Завдяки підозрілому додатку, ваш додаток знає, куди йти самостійно. Набагато ефективніше.
Це те саме, що №2 насправді.
Чи знаєте ви про якісь цікаві проекти чи інструменти в цій галузі?
Кілька нових проектів у цьому просторі:
Осколок-запит - це рішення для шардінгу на основі OLAP для MySQL. Це дозволяє визначити комбінацію шардованих таблиць і неархівованих таблиць. Незатемнені таблиці (як таблиці підстановки) можуть вільно приєднуватися до шардованих таблиць, і шардовані таблиці можуть приєднуватися одна до одної, доки таблиці приєднуються клавішею осколка (жоден поперечний осколок або самоз'єднання, які перетинають межі осколка). Будучи рішенням OLAP, Shard-Query зазвичай має мінімальний час відгуку 100 мс або менше, навіть для простих запитів, тому він не буде працювати для OLTP. Shard-Query призначений для паралельного аналізу наборів великих даних.
Рішення для шардінгу OLTP існують і для MySQL. Закриті вихідні рішення включають ScaleDB , DBShards . Рішення OLTP з відкритим кодом включають JetPants , Cubrid або Flock / Gizzard (інфраструктура Twitter).
Рівень застосування, звичайно.
Найкращий підхід, який я коли-небудь червонів, я знайшов у цій книзі
Високопродуктивний MySQL http://www.amazon.com/High-Performance-MySQL-Jeremy-Zawodny/dp/0596003064
Короткий опис: ви можете розділити свої дані на багато частин і зберегти ~ 50 частин на кожному сервері. Це допоможе вам уникнути другої за величиною проблеми шардингу - перебалансування. Просто перемістіть деякі з них на новий сервер, і все буде добре :)
Я настійно рекомендую вам придбати його та прочитати частину "масштабування mysql".
Станом на 2018 рік, схоже, існує власне рішення MySql. Насправді існує принаймні 2 - кластер InnoDB та кластер NDB (існує комерційна та спільна версія).
Оскільки більшість людей, які використовують версію спільноти MySql, більше знайомі з движком InnoDB, саме це слід вивчити як першочергове завдання. Він підтримує реплікацію та розділення / виділення з коробки та заснований на MySql Router для різних варіантів маршрутизації / балансування навантаження.
Синтаксис для створення таблиць потрібно змінити, наприклад:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATETIME) PARTITION BY HASH ( YEAR(col3) );
(це лише один з чотирьох типів розділів )
Одне дуже важливе обмеження:
Зовнішні ключі InnoDB та розділи MySQL не сумісні. Розділені таблиці InnoDB не можуть мати посилання на зовнішні ключі, а також не можуть мати стовпців, на які посилаються зовнішні ключі. Таблиці InnoDB, які мають або на які посилаються зовнішні ключі, не можуть бути розділені.
PARTITION BY HASH(YEAR...)скануватиме всі розділи, якщо у вас є діапазон дат. Гидота.