Elasticsearch як база даних NoSQL
Чи може пошуковий сервер Elasticsearch використовуватися як NoSQL бази даних? Позитивна відповідь дозволить розглянути його різні властивості, в тому числі і ті, від реалізації яких він відмовився, щоб стати одним з найбільш гнучких, продуктивних і масштабованих пошукових движків. Але для відповіді на це питання варто спочатку визначитися з самим терміном NoSQL, оскільки залежно від контексту він може трактуватися по-різному.
Що ж все-таки таке NoSQL?
Розробники NoSQL дають таке визначення: база даних наступного покоління, що характеризується відмовою від реляційності, розподіленістю, відкритістю вихідних текстів і горизонтальною масштабованістю. Назвати це визначення точним, на жаль, не можна.
Справа в тому, що мова йде зовсім не про SQL. Пояснимо. Мова запитів Hive явно була натхненна SQL. Це ж можна сказати і про мову Esper, хоч вона працює і не з потоками, а з відносинами. Цікава історія PostgreSQL - спочатку він називався Postgres, в якості мови запитів використовував Quel і був ORDBMS, а сьогодні PostgreSQL володіє багатьма функціями, які дозволяють йому бути документноорієнтованим сховищем.
В даному випадку мова йде не про ACID - у визначенні NoSQL про транзакції нічого не говориться. Hyperdex - це база NoSQL, яка прагне забезпечувати ACID-транзакції. MySQL, безсумнівно, є базою SQL і в своїй історії має сумнівні інтерпретації на тему, що ж насправді означає ACID.
Стосунки. Більшість баз даних NoSQL не підтримує операцію join так, як це роблять традиційні реляційні бази даних, і залишають цю роботу користувачеві. Але існують і такі бази даних, які виконують цю роботу самостійно, наприклад, RethinkDB, Hive і Pig. Графова база даних Neo4j також працює з відносинами - в обході відносин (ребер) графа. У Elasticsearch є поняття join часу запиту для відносин parent/child і join часу індексації, яке реалізовано за допомогою nested type.
Розподілення. Зазвичай бази даних SQL не є розподіленими, а NoSQL, навпаки, - розподілені. Існують також і проекти (node.js NoSQL, ejdb), схожі на NoSQLite. Однак бази даних нового покоління прагнуть забезпечити розподіленість тим чи іншим чином.
Тобто не можна точно визначити поняття NoSQL і віднести Elasticsearch до сховища NoSQL. Вже на момент створення статті nosql-database.org містив понад 20 подібних баз даних.
Далі ми розглянемо деякі важливі властивості і побачимо, як Elasticsearch реалізує їх.
Відсутність транзакцій
Lucene, на основі якої побудовано Elasticsearch, має підтримку транзакцій, хоча Elasticsearch при цьому не має транзакцій у звичному розумінні цього слова. Тобто відкотити відправлений документ або працювати з групою документів атомарно неможливо. Натомість Elasticsearch має функцію write-ahead-log, що забезпечує надійність операції і виключає необхідність використовувати дорогий Lucene-коміт. Також можна вказати рівень консистентності операцій індексування, тобто скільки реплік повинні визнати операцію перш, ніж повернути результат. Типовим є кворум, тобто n/2+1.
Elasticsearch забезпечує маніпуляції з даними і пошук практично в реальному часі. Типово, між індексуванням/оновленням/вилученням даних і появою цих змін у результатах пошуку проходить одна секунда. Це відрізняє Elasticsearch від систем SQL, в яких всі зміни видно після завершення транзакцій.
Оптимістичний конкурентний контроль (optimistic concurrency control) здійснюється шляхом зазначення версії надісланих документів.
Сервер Elasticsearch створений для швидкості, але здійснення розподілених транзакцій займає багато часу, а їх відсутність робить роботу простішою. Можна погодитися отримувати дещо застарілі дані, зате всі будуть спостерігати однакову часову шкалу, а в кеші Elasticsearch буде зберігатися велика кількість даних, що робить цей сервер максимально продуктивним, адже за це його і люблять.
Гнучкість схеми даних
В Elasticsearch не треба вказувати схему даних заздалегідь. Достатньо надіслати JSON-документ, і сервер сам виконає необхідні операції, щоб визначити його тип. Це добре працює, коли мова йде про числові і логічні типи даних і про часові мітки. Для рядків буде використано стандартний аналізатор, який підходить для базових операцій.
Те, що «безсхемність» (у тому сенсі, що не треба самостійно визначати схему) можна уявити як «гнучку схему», спірно. Щоб розробити відмінний пошук і систему аналітики, слід спроектувати власну схему даних. Для цього у Elasticsearch є великий набір потужних інструментів, наприклад, dynamic templates, multi-field objects тощо. Більш детально про це можна почитати в статті про мапінг.
Відносини та обмеження
Elasticsearch - документоорієнтована база даних: весь пул об'єктів, за яким ви збираєтеся робити пошук, повинен бути проіндексований, а значить, перед індексацією документи повинні бути денормалізовані. Це збільшує продуктивність витягу (оскільки вам не потрібні join-запити), вимагає більше дискового простору (через зберігання надлишкової інформації), але при цьому забезпечити консистентність і актуальність даних (будь-який вимір зачіпає всі документи, що містять змінюваний об'єкт) стає складніше. Однак це ідеальний варіант, якщо документ необхідно зберегти один раз, а читати його будуть багато разів.
Наприклад, ви створили базу даних, в яку занесли клієнтів, замовлення та продукти, і тепер хочете знайти замовлення, що містять певну назву продукту та ім'я користувача. Це завдання вирішується за допомогою індексації замовлень з усією необхідною інформацією про користувача і продукти. Операція пошуку досить легка, але що буде, якщо ви захочете змінити назву продукту? У реляційних базах даних з правильною нормалізацією досить просто оновити продукт - у цьому їх зручність. Але у випадку з денормалізованою документною базою даних вам доведеться оновити кожне замовлення з цим продуктом.
Іншими словами, при роботі з документоорієнтованими базами даних, як Elasticsearch, проектується маппінг, і документи зберігаються в оптимальному для пошуку і вилучення вигляді.
Як говорилося раніше, в Elasticsearch є поняття join часу запиту для відносин parent/child і join часу індексації на основі nested type. Більш детально ми, ймовірно, поговоримо про це в наступній статті, але при бажанні можете ознайомитися з презентацією Мартіна ван Гронінгена (Martijn van Groningen) «Document relations with Elasticsearch».
Більшість реляційних баз даних також дозволяє задавати обмеження, щоб визначити, що є консистентним, а що ні. Наприклад, у них може бути забезпечена посилальна цілісність та унікальність, зазначено, що сума операцій з рахунком має бути позитивною тощо. Документоорієнтовані бази даних, як правило, цього не роблять, і Elasticsearch не виняток.
Надійність або стійкість до падіння (robustness)
База даних повинна бути надійною, особливо якщо вона є основним сховищем інформації. В ідеалі, в ній повинна бути передбачена можливість скасування ресурсоємного запиту і, звичайно, вона не повинна перестати працювати, поки ви самі цього не захочете.
На жаль, Elasticsearch, як і компоненти, з яких він побудований, в даний час погано обробляють OutOfMemory-помилки. Більш детально ми зупинимося на цьому в статті «Elasticsearch in Production, OutOfMemory-Caused Crashes». Важливо забезпечити Elasticsearch достатнім обсягом пам'яті і бути обережним перед запуском запитів з новими невідомими вимогами до пам'яті на виробничому кластері.
Хоча це, ймовірно, буде виправлено в міру розвитку Elasticsearch, слід пам'ятати, що Elasticsearch створювався для високої швидкості, і передбачалося, що оперативної пам'яті на сервері буде в надлишку.
Розподілення
Див. також: Elasticsearch in Production, Networking
До того, як Шей Бенон (Shay Banon) створив Elasticsearch, він працював над Compass. У певний момент він зрозумів, що перетворити Compass на розподілений пошуковий движок занадто складно, і почав створення Elasticsearch з нуля. Elasticsearch спроектовано розподіленим і легко масштабується для обробки великих обсягів даних на доступному залізі.
Elasticsearch неймовірно простий у використанні і підходить для тих, хто тільки починає свою роботу з розподіленими системами, хоч вони і досить складні. Докладніше ми розглянемо цей момент у наступних розділах.
Сама природа розподілених систем передбачає, що є безліч речей, які можуть піти не так. Насправді, у різних баз даних є різні переваги: одні прагнуть до високої стабільності, інші - до постійної доступності, хоч і можуть повертати помилкові результати протягом деякого або навіть тривалого часу. По ідеї база даних рідко стикається з проблемами і при необхідності швидко вирішує їх, як показав у своєму дослідженні ризиків поділу мережі на частини Кайл Кінгсбері (Kyle Kingsbury). Він показав, що в той час як база даних працює добре, всередині неї відбувається велика кількість операцій з усунення можливих неполадок.
З точки зору консистентності, доступності та стійкості до збоїв мережі, Elasticsearch - це CP-система (consistency & partition tolerance) для досить слабкого визначення терміну «консистентність». Якщо переважають операції, пов'язані тільки з читанням, Elasticsearch дозволяє досягти AP-поведінки (availability & partition tolerance) шляхом зменшення параметра minimum master nodes, тобто відсутністю кворуму. Однак зазвичай необхідно, щоб більшість вузлів у кластері було доступно. Без цієї більшості запис у неправильно сконфігурований кластер, тобто кластер з «розділеним мозком» (split brain), може призвести до безповоротної втрати даних. Це ні в якому разі не є специфікою Elasticsearch і характерно і для інших серверів.
Elasticsearch має власний алгоритм вибору «майстра». Він досить простий і не особливо стійкий, що, на жаль, може стати причиною великих бід у реальному світі мережевих проблем. У Found ми керуємо сотнями кластерів і бачимо проблему вибору «майстра» досить часто, тому активно працюємо над переміщенням вибору «майстра» в Zookeeper, який ми вже використовували для багатьох інших цілей.
З точки зору масштабування індекс складається з одного або декількох шардів (shard), кількість яких вказується в момент створення індексу і після вже не може бути змінено. Таким чином, індекс повинен бути розбитий на шарди пропорційно очікуваному зростанню. Якщо в кластер Elasticsearch додається все більше вузлів, то він грамотно перерозподіляє і переміщує шарди. Так що можна сказати, що Elasticsearch легко масштабувати.
Безпека
Див. також: Elasticsearch in Production, Security
Elasticsearch не має можливості для ідентифікації або авторизації. Вам треба враховувати, що будь-який користувач може підключитися до вашого Elasticsearch-кластеру і отримати права суперкористувача, особливо якщо дозволена підтримка скриптів.
Резюме
Безумовно, Elasticsearch, можна використовувати як основне сховище, якщо описані вище обмеження не є для вас проблемою. Хороший приклад - Logstash, фантастичний інструмент для управління логами. Він зберігає їх в Elasticsearch і має можливість зберігати їх в іншому місці. Логи пишуться один раз, а читаються при цьому багато. Якщо немає оновлень, то немає і необхідності в транзакціях, забезпеченні цілісності та ін.
А як щодо таких систем, як Postgres, які підтримують повнотекстовий пошук і ACID-транзакції (інші приклади - повнотекстові можливості MySQL, MongoDB, Riak тощо)? У Postgres можна реалізувати базовий пошук, але варто згадати про величезний розрив з Elasticsearch як у продуктивності, так і в інших особливостях. Як говорилося в розділі про транзакції, Elasticsearch може хитрувати і використовувати кешування, не піклуючись про multi version concurrency control та інші ускладнюючі роботу речі. Пошук - це щось більше, ніж просто знаходження ключового слова в частині тексту. Мова йде про застосування спеціальних знань для реалізації хороших моделей релевантності, що дають огляд можливих результатів і роблять такі речі, як перевірка орфографії та автозавершення, до того ж виконуючи все це дуже швидко.
Elasticsearch зазвичай використовується як доповнення до іншої, основної, бази даних - з сильним акцентом на обмеження, коректність і надійність, а також транзакційно оновлюваної. Відповідно, дані спочатку записуються на основну базу, а потім асинхронно - в Elasticsearch. Докладніше про синхронізацію даних можна дізнатися з наступної статті. У себе в Found ми зазвичай використовуємо ZooKeeper, а також PostgreSQL як основну базу, яку ми доповнюємо Elasticsearch для відмінного пошуку.
Як і в усьому іншому, не існує однієї бази даних для управління всією вашою інформацією. Для хорошої роботи вам обов'язково треба знати всі сильні і слабкі сторони вашого сховища.
Рекомендована література
Shay Banon: The Future of Compass & Elasticsearch // www.kimchy.org/the_future_of_compass
PS. Дякую редактору перекладу Анастасії Гордок.



