Pull to refresh

Elasticsearch как NoSQL база данных

Reading time 8 min
Views 60K
Original author: Alex Brasetvik
Может ли поисковый сервер 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. Спасибо редактору перевода Анастасии Гордок.
Tags:
Hubs:
+24
Comments 10
Comments Comments 10

Articles