С чего начинается Elasticsearch

Elasticsearch, вероятно, самая популярная поисковая система на данный момент с развитым сообществом, поддержкой и горой информации в сети. Однако эта информация поступает непоследовательно и дробно.


Самое первое и главное заблуждение — "нужен поиск, так бери эластик!". Но в действительности, если вам нужен шустрый поиск для небольшого или даже вполне себе крупного проекта, вам стоит разобраться в теме поподробней и вы откажетесь от использования именно этой системы.


Вторая проблема заключается в том, что пытаясь разобраться с начала, получить общую картину окажется непросто. Да инфы навалом, но последовательность в ее изучении выстраивается постфактум. Придется из книг бежать в документацию, а из документации обратно в книги, параллельно разгугливая тонкости, только чтобы понять, что такое Elasticsearch, почему он работает именно так и для чего же его вообще использовать, а где стоит выбрать что-то попроще.


В этой статье я попытался последовательно объяснить то что мне кажется главным в Elasticsearch, то для чего он был придуман и как он устроен.


Для наглядности выдумаем себе задачу. Реализация поиска в коллективном блоге по всем материалам и пользователям. Система позволяет создавать теги, сообщества, геометки и все остальные штуки, которые нам помогают категоризировать огромное количество информации.


Схема хранения данных


То, какие действия с данными мы будем производить определит схему их хранения:


  • скорее всего поисковая система должна будет быстро производить поиск
  • запись и удаление могут не отличаться высокой скоростью, в системах поиска, полагаю, этим можно пренебречь
  • структура данных будет интенсивно изменяться и хранилище может заполняться из нескольких независимых источников( различных баз, в том числе внешних для нашей системы )

Представьте еще раз сколько атрибутов может иметь публикация и сколько связанных с ней объектов. Автор, категория, сообщество, геометки, медиафайлы, теги, связанные публикации. Этот список можно продолжать до исчерпания фантазии. Если мы храним это в привычной реляционной базе то имеем миллион связей и миллиард атрибутов. Это прекрасно подходит для структурированного хранения долгие годы, но не очень вяжется с требованиями быстрого поиска.


А что если мы захотим добавить пару интеграций с внешними системами? Придется реализовать дополнительные таблицы или даже базы. Нам всегда будет нужно что-то добавить или изменить в объектах доступных для поиска. Вы понимаете к чему я клоню.


Намного быстрее читать из объектов, содержащих все необходимое здесь и сейчас. И намного проще вносить изменения в неструктурированную схему данных.



{
    "title" : "С чего начинается Elasticsearch",
    "author" : {
        "name": "Roman"
    },
    "content" : "Elasticsearch, вероятно, самая популярная поисковая система...",
    "tags":[
        "elasticsearch"
    ],
    "ps": "Да, проще всего представить это как JSON, BSON или XML"
}

К тому же такие структуры данных проще делить, разносить по разным физическим хранилищам, распределять, ведь объекты уже содержат все необходимое.


Эти объекты мы можем воспринимать как отдельные страницы, файлы, карточки, все это можно назвать некими документами. Поэтому такая модель хранения данных называется документоориентированной.


Elasticsearch это документоориентированная база данных

Поиск


Теперь необходимо определиться с механизмами поиска. Данные организованы в виде документов. Как мы привыкли осуществлять поиск по документу?


Типичным примером документа будет веб-страница. Если мы попытаемся поискать по всей странице в браузере, поиск будет осуществляться по всему содержащемуся тексту. И это удобно для большинства кейсов.


Примерно так же работают многие поисковые системы, поиск происходит по всему тексту проиндексированных страниц, а не по отдельным полям, тегам или заголовкам. Это называется полнотекстовым поиском.


Искать предстоит по огромному количеству документов и было бы разумно запомнить что в каком документе лежит. В реляционных СУБД мы привыкли оптимизировать подобный поиск индексами.


Что такое индекс на самом деле? Если не вдаваться в детали, индекс это сбалансированное дерево, то есть дерево, в котором длина путей(количество шагов межу узлами) не будет отличаться больше чем на один шаг.



Например если бы мы проиндексировали наш пост, то у нас бы получилось дерево, листьями которого, являлись бы используемые в нем слова. Простыми словами, мы будем знать заранее, какие слова находятся в документе и как их быстро в нем найти. Не смотря на такую удобную структуризацию данных, обход дерева звучит как не самое лучшее решение для максимально быстрого поиска.


А что если сделать все наоборот — собрать список всех используемых слов и узнать, в каких документах они встречаются. Да, индексация займет больше времени, но нас в первую очередь интересует именно скорость поиска, а не индексации.



Такой индекс называется обратным индексом и используется для полнотекстового поиска.


Хороший пример — популярная open-source библиотека полнотекстового поиска, конечно же, с обратным индексом, Apache Lucene.


Elasticsearch использует индексы Lucene для хранения данных и поиска

Масштабирование


Как бы мы не пытались оптимизировать структуры данных и алгоритмы поиска, когда речь заходит о действительно больших массивах данных и действительно большом количестве запросов, необходимо задуматься о возможности повлиять на производительность системы путем увеличения аппаратного ресурса. Проще говоря, мы хотим иметь возможность накинуть немного памяти, ЦП и дискового пространства, чтобы все ехало быстрее. Мы можем назвать это масштабируемостью.


Самый простой вариант — накинуть железа на сервер. Если представить каждую условную единицу вычислительной мощности как деревянный кубик, то сейчас мы сложим кубики в одно место или один на другой, строя башню вертикально. Такое масштабирование и называется вертикальным.


Второй вариант — разделить наши задачи на группу машин. В этом случае мы тоже увеличиваем аппаратный ресурс, но сейчас кубики мы можем расположить на воображаемом столе как угодно на его плоскости, то есть горизонтально. Угадайте, как называется такое масштабирование?


Первый способ гарантирует нам быстрый результат без боли, но конечно не все так гладко. Как долго мы сможем увеличивать ресурс отдельной машины? Во-первых дешевым способом это будет только в самом начале, дальше оплата одного сервера будет стоить как несколько машин попроще. Во-вторых вы рано или поздно упретесь в потолок — железо, драйверы, пропускная способность и еще куча логических и физических ограничений. А самое главное, критический сбой в одной машине повлечет сбой всей системы, закономерно.


В отличии от первого способа второй не накладывает таких явных ограничений, мы можем добавлять машины сколько угодно, связывая их сетью. Конечно, это повлечет сетевые издержки — низкая скорость передачи в сети(в сравнении с обработкой на одной машине), сетевой оверхед. Но вместе с тем сеть имеет одно очень важное свойство — большую отказоустойчивость.


Распределенный индекс


Ок, для хранения данных и поиска мы будем использовать инстанс Lucene. Но ранее мы решили, что для обеспечения горизонтального масштабирования нам необходимо иметь возможность размещать данные на разных машинах. В действительности, какая разница как данные хранятся физически? Важно чтобы мы имели единое логическое хранилище. Каждый инстанс Lucene должен стать частью одного большого индекса, или осколком(shard) разбитого индекса. Шард будет выполнять непосредственно операции по поиску и записи данных.



Shard в Elasticsearch — это логическая единица хранения данных на уровне базы, которая является отдельным экземпляром Lucene.

Index — это одновременно и распределенная база и механизм управления и организации данных, это именно логическое пространство. Индекс содержит один или более шардов, их совокупность и является хранилищем.

Классическое сравнение индекса с другими базами выглядит примерно так.
Elasticsearch SQL MongoDB
Index Database Database
Mapping/Type Table Collection
Field Column Field
Object(JSON) Tuple Object(BSON)


Но существуют отличия в использовании этих абстракций. Рассмотрим еще один классический пример. У пользователя системы может храниться очень много информации, и мы решаем создавать новую базу для каждого пользователя. Это звучит дико! Но на самом деле в Elasticsearch это распространенная и даже хорошая практика. Индекс это довольно легкий механизм и лучше разделять большие данные, тем более, когда это логически оправдано. Системе проще работать с небольшими индексами чем с разросшейся базой для всего. Например, так вы можете создавать отдельный индекс для логов на каждый день и это широко используется.

По умолчанию количество шардов для индекса будет равным 5, но его всегда возможно изменить в настройках index.number_of_shards: 1 или с помощью запроса шаблонов индекса.
PUT _template/all
{
  "template": "*",
      "settings": {
        "number_of_shards": 1
      }
}


Важно управлять этим значением. Всегда принимайте решения с точки зрения параллельной обработки.

Каждый шард способен хранить примерно 232 или 4294967296 записей, это значит, что скорее всего вы упретесь в лимит вашего диска. Однако стоит понимать, все шарды будут участвовать в поиске и если мы будем искать по сотне пустых, потратим время впустую. Если шарды будут слишком большими мы так же будем тратить лишнее время на поиск, а так же операций перемещения и индексации станут очень тяжелыми.

Забегая вперед. Со временем Elasticsearch двигает и изменяет шарды, объединяя дробные и мелкие в большие. Следите за размером ваших шардов, при достижении 10ГБ производительность значительно падает.

Кластер


Мы определились с базовой концепцией распределенного индекса. Сейчас необходимо решить, как в действительности будет осуществляться управление отдельными базами.


Ранее мы решили, что за операции поиска и индексации отвечает отдельный инстанс Lucene(шард). Для того, чтобы обращаться к распределенной системе шардов, нам необходимо иметь некий координирующий узел, именно он будет принимать запросы и давать задания на запись или получение данных. То есть помимо хранения данных мы выделяем еще один вариант поведения программы — координирование.


Таким образом мы изначально ориентируемся на два вида узлов — CRUD-узлы и координирующие узлы. Назовем их data node и coordinating node. У нас есть куча машин объединенных в сеть и все это очень напоминает кластер.



Каждый запущенный экземпляр Elasticsearch является отдельным узлом(node). Cluster — это совокупность определенных нод. Когда вы запускаете один экземпляр ваш кластер будет состоять из одной ноды.

Для того чтобы объединить узлы в кластер они должны соответствовать ряду требований:
  • Ноды должны иметь одинаковую версию
  • Имя кластера cluster.name в конфигурации должно быть одинаковым


Конфигурация читается из файла elasticsearch.yml и переменных среды. Здесь мы можете настроить почти все, что касается неизменных в рантайме свойств ноды.

Вы можете поднимать несколько узлов на одной машине, для этого необходимо запускать инстансы из разных директорий файловой системы и в конфигурации указать разные порты http.port, по умолчанию порт 9200 для внешнего доступа и 9300 для внутрикластерного соединения. Это может понадобиться для тестирования и проектирования кластера, однако в проде подразумевается использование отдельных машин.

Каждый тип ответственности узлов налагает определенные системные требования. Очевидно, что data-ноды будут часто обращаться к диску и использовать значительные объемы памяти в процессе работы.


Мы так же можем утверждать, что не все данные будут запрашиваться одинаково часто. Данные постепенно "остывают" по мере снижения запросов. Мы можем назвать это жизненным циклом хранения данных. Хорошей идеей было бы держать хайповые публикации там, откуда их можно быстро достать, а забытые мемы 2007 можно положить подальше.


Начиная с версии 6.7 Elasticsearch предлагает механизм управления жизненным циклом. Для этого доступны три типа нод — hot, warm и cold.

Существует рекомендация по выбору аппаратных конфигураций для каждого из типов. Например hot-ноды должны иметь быстрые SSD, для warm и cold достаточно HDD-диска. Оптимальные соотношения память/диск будут следующими:
  • hot — 1:30
  • warm — 1:100
  • cold — 1:500


Для того чтобы определить тип ноды как data node необходимо установить значение в конфигурации node.data: true, при этом рекомендуется выделять ноду под один конкретный тип, для повышения стабильности и производительности кластера.

Важнейшим аспектом в использовании распределенных систем является параллельное выполнение задач. Существует популярная модель распределенных вычислений, которая имеет лаконичное название MapReduce. И заключается она разделении выполнения задачи на два больших шага:


  • Map — предварительная обработка данных, формулировка задачи и последующая ее передача выполняющим узлам
  • Reduce — свертка множества результатов worker-нод в один финальный ответ


Именно такой механизм поможет нам выполнять операции с шардами. Координирующий узел получит запрос, предварительно переформулирует его для внутрикластерного взаимодействия и выполнит запросы к нашим worker-нодам(в данном случае к data-нодам).


Следовательно, coordinating-ноды должны иметь достаточный ресурс памяти, ЦП и быструю сеть, но при этом могут иметь скромный диск, ведь не осуществляют хранения данных.


Однако при большой частоте запросов, такие ноды могут стать узким местом системы. Мы можем пойти привычным путем и превратить точку внешнего доступа в плоскость. Пусть координирующих нод будет множество.


Такой подход позволит нам применять балансировку запросов, это можно сделать прямо в клиентском коде либо использовать любые существующие балансировщики.


В Elasticsearch все узлы неявно являются координирующими. Однако, стоит выделять отдельные coordinating-ноды, не выполняющие других операций. Забегая вперед, такие ноды можно определить, установив значения всех типов в false.

Управление кластером


На данном этапе мы имеем возможность доступа к данным из множества точек — coordinating-нод. В этом нет проблем, если мы говорим о простых операциях чтения/записи в существующий индекс. Но если говорить о выделении новых шардов или их перемещении, может начаться путаница.


Предположим, возможность coordinating-нодам управления состоянием кластера. Один узел примет решение о перемещении шарда на одну data-ноду, а второй о перемещении того же на другую. Список возможных общекластерных действий может быть довольно широким, а список возможных конфликтов еще шире.


Очевидно такие важные решения должен принимать один центральный узел. Мы определили, что для каждого типа действий необходимо выделять отдельную роль, чтобы избежать потерь производительности на ноде. И "главный в кластере" звучит как отдельная ответственность.


Назовем такие ноды master-node. Активный мастер всегда должен быть один, он будет управлять топологией кластера: создавать новый индекс, выделять и распределять шарды, перемещать их и объединять в случае необходимости. Мастер всегда знает все о состоянии кластера.


В кластере Elasticsearch обязательно должен быть как минимум один узел отвечающий требованиям master node. Для этого в конфигурации ноды необходимо установить значение node.master: true.

Master-ноды отвечают за важные, но довольно легкие общекластерные действия. Это означает, что они требуют большого ресурса и высокой стабильности от физической ноды. В кластерах от 10 нод необходимо всегда выделять отдельные only-master узлы.

Репликация данных


Сейчас каждая запись в нашем индексе существует только в одном месте, и потеря хранящего ее узла приведет к потере данных на неопределенный срок. Для того, чтобы этого избежать существует механизм репликации. Важно не путать понятия реплики и бэкапа, если бэкап позволяет восстановить данные в случае утери, то реплика является полной копией базы.


Если мы потеряем одну из data-нод, то всегда сможем продолжить работу с репликами шардов в другом узле и тем временем вернуть потерянный.


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



Чтобы жестко установить количество реплик индекса используется параметр number_of_replicas. Так же мы можем изменить это значение в рантайме выполнив запрос:
PUT / _settings {
  "index": {
      "number_of_replicas": someVal
  }
}

Таким образом мы всегда имеем реплики всех шардов и не поднимаем неэффективно простаивающие ноды.


Основной шард назовем первичным или primary shard, а любую из его копий реплицирующим шардом или replica shard, первичный шард и его реплики это группа репликации.


С учетом реплик запись данных будет происходить в два этапа, в первом запись затронет только первичный шард и только после того, как произойдет операция flush слияния изменений и операция commit фиксации в индексе Lucene, будет отправлен внутренний запрос на изменение всех реплик.



Для мониторинга состояния кластера в Elasticsearch существует cluster health status. Статус может иметь три значения:
  • green — все ок
  • yellow — есть утраченные шарды, кластер полностью работоспособен, но едет на репликах
  • red — есть утраченные шарды, кластер неработоспособен или часть данных недоступна

Для максимальной стабильности кластера необходимо, чтобы количество дата-нод было больше или равно количества реплик.


Отказоустойчивость


Сейчас данные будут доступны даже в случае сбоя одного из хранящих узлов. Но что если кластер потеряет мастера? Потеря единственного мастера равноценна потере кластера.


Тут все по привычной схеме — поднимаем несколько мастеров.


Но если у нас есть, например, два управляющих узла, как понять, какой из них в данный момент должен управлять кластером? Как они смогут договориться о своих решениях? Очевидно, что в каждый момент времени должен быть только один управляющий кластером узел.


То есть при потере мастера его место должен занять один из кандидатов.


В Elasticsearch настройка node.master: true не будет означать, что данный узел является мастером, это всего лишь скажет о том, что он может быть выбран в качестве главного узла. По умолчанию настройки будут установлены следующим образом:
  • node.master: true
  • node.data: true

Представим. Главный управляющий узел стал недоступен для кластера, кластер берет первого кандидата и устанавливает его на вакантное место. Спустя определенное время первый мастер возвращается в кластер и ничего не знает о том, что его место уже занято. Мастер-ноды являются своего рода его мозгом, и теперь мозг кластера становится разделен. Это классическая проблема распределенных систем и она так и называется split-brain problem.



В обществе подобные проблемы зачастую решаются путем голосования. Подобный механизм используется и в распределенных системах. Как только кластер теряет управляющий узел, должен быть запущен процесс голосования.


Важно определить какой из кандидатов больше всего подходит на роль главного узла. Такой кандидат должен обладать самой актуально информацией о кластере. Для краткого описания актуальности информации о кластере может использоваться версионирование. При каждом изменении кластера главный узел будет обновлять некую служебную информацию и повышать номер версии, далее то же самое будет параллельно происходить в нодах-кандидатах.


Сравнив номера версий мы можем определить наиболее подходящих кандидатов на роль мастера. Теперь если отпавшая мастер-нода вернется в кластер, то процесс голосования запустится снова и будет выбран единственный управляющий узел.



Теперь важно понять когда можно считать, что голосование прошло успешно? Если проголосовали все участники? Или половина? Или другое любое другое магическое количество?


Решение этой проблемы заключается в определении кворума. Это умное название для контрольного количества голосующих.


Очевидно, что такое важное решение как выбор мастера должно приниматься на основе большинства, то есть 50%+один голос. Справедливо, надежно. Это значение и станет кворумом.


Таким образом, количество кандидатов на мастера должно быть нечетным и не меньше трех. Рекомендуется использовать простую формулу для расчета оптимально количества таких нод:
КОЛИЧЕСТВО_КАНДИДАТОВ = ОБЩЕЕ_КОЛИЧЕСТВО_НОД/2 + 1


Решения для любых общекластерных действий принимаются путем голосования, и вся необходимая для голосования информация содержится в конфигурации голосования. Право голоса определяет еще одну роль, ведь право голоса не означает, что узел может быть кандидатом.


В Elasticsearch узлы, которые могут участвовать в голосовании можно определить в конфигурации: node.voting_only: true.

Elasticsearch автоматически изменяет конфигурацию голосования при изменении кластера. Поэтому нельзя одновременно отключать половину или более голосующих нод. Например, если в вашей конфигурации в данный момент 7 голосующих нод и вы отключили сразу 4, кластер станет недоступным, потому что останется 3 ноды, а в конфигурации голосования кворумом является значение 4.

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


Транспорт


Пришло время поговорить о том, как общаться с кластером из внешних систем, и как будут общаться узлы внутри кластера. Есть ряд плюсов и минусов использования и традиционных, и специальных протоколов. Для краткого сравнения существует таблица.


Протокол Достоинства Недостатки
HTTP Низкий порог вхождения, в сравнении с нативным протоколом. Для использования нужен только HTTP клиент и погнали. HTTP API никогда не ломает совместимость, при обновлении версии ES, ваше приложение продолжит работать так же. Возможно проксировать и использовать балансировщики нагрузки. JSON. Клиент не знает топологию кластера, поэтому может потребовать большее количество запросов для получения данных. Оверхед.
ES Native Лучший выбор для ОЧЕНЬ больших данных. Если необходимо выполнить большое количество операций с индексом, нативный протокол значительно ускорит. Используется под JVM. Использование влечет жесткую связность с ES. Обновления требуют перекомпиляции и повторного развертывания пользовательских клиентов. Возможны обновления ломающие совместимость.

Для внутренней коммуникации в кластере Elsaticsearch использует нативный протокол.

Заключение


Хочется верить, что прочитав эту статью вы поняли основы распределенных поисковых систем. Возможности масштабирования и отказоустойчивости — это то для чего был создан Elasticsearch и то, почему он приобрел популярность.


Я постарался кратко и последовательно рассказать о том, как и почему именно так это устроено. В этой статье я намеренно не стал упоминать об экосистеме Elastic, плагинах, запросах, токенизации, маппинге и остальном. Так же я не сказал об Ingest и machine learning нодах, на мой взгляд, они дают дополнительные возможности и не являются базовыми.


Дополнительные материалы


Elastic Stack and Product Documentation


Сайзинг Elasticsearch


Книга Elasticsearch 5.x Cookbook, Third Edition

Комментарии 44

    +2
    Но в действительности, если вам нужен шустрый поиск для небольшого или даже вполне себе крупного проекта, вам стоит разобраться в теме поподробней и вы откажетесь от использования именно этой системы.


    И что же использовать?
      0

      Есть SphinxSearch. Для совсем небольшего проекта может хватить PostgreSQL FTS. Есть ещё масса проектов, все названия не упомнить.

        0
        + Graylog
          +1
          Elastic — в каком-то смысле «обёртка» над Lucene.
          Graylog — в каком-то смысле «обёртка» над Elastic.

          Elastic поверх Lucene добавляет отказоустойчивость, удобный API и другие плюшки.
          А вот чего такого добавляет Graylog, что для поиска он становится удобней Elastic'a?
          У Graylog есть фишки заточенные под сбор логов: доставка логов, алёрты из коробки и т.д., но в плане поиска есть ли у него какие преимущества?
            +2
            Логи грейлог сам не доставляет, скорее грейлог это замена логстэшу и эластик кластер для грейлога создается отдельно (правда только версия эластика не выше шестерки). А так там тотже lucene query syntax для поиска.
              0
              Всё верно. Я это и имел в виду:
              Для Graylog создаётся Elastic (вернее Graylog его создаёт и активно им управляет).
              Плюс у Graylog своя обвязка вместо Kibana, Logstash и *beats.
          0
          SphinxSearch прекрасен, если научиться его готовить.
            +6

            Да, я вообще много раз сталкивался с тем, что ES использовали совсем не к месту, там, где вполне хватало встроенного в PostgreSQL FTS.


            ElasticSearch у всех на слуху, это порождает ситуацию, когда менеджеры не думая навязывают ES, с противоположной стороны разработчики тоже используют его не особенно задумываясь.


            У меня отличные впечатления как от PostgreSQL FTS (но после определенного предела нагрузки он не тянет), так и от SphinxSearch (его используют такие монстры, как Craigslist и Avito). Но о них мало кто пишет, увы. Гораздо больше статей типа: «У меня сервис с 10 пользователями, и чтобы искать пользователя по имени или email, я внедрил кластер на 10 инстансах Elasticsearch, сейчас расскажу вам как». Overengineering хорошо продается работодателям, которые не в теме.

              0

              Да, Sphinx отлично себя зарекомендовал. На данный момент я пока не сталкивался с задачами по поиску, которые он бы с блеском не решал. Но в AWS есть managed elasticsearch и нет managed sphinx, и вообще product awareness у Sphinxsearch не очень. Даже на постсоветском пространстве далеко не каждый вспомнит про него, что уж говорить о Европе / США. А зря — это реально классная, полнофункциональная, производительная альтернатива ES.

                0
                У них большие проблемы с брендингом, маркетингом и позиционированнием. Например, открыл их сайт — там http (на дворе 2020 год если что и гугл, например не шттпс выдает ниже в выдаче, если вообще выдает). Сайт выглядит так как будто не менялся с 2001.
                0

                А как у PostgreSQL FTS c интерналицизацией? Поиск по записям на английском, немецом, франзуском, итальянском в частности, с учётом типовых замен букв с умляутами на латинские пары?

                  0

                  С поддержкой языков все в порядке, основные европейские языки, включая русский, поддерживаются.


                  Поиск одновременно на нескольких не использовал, но думаю, что можно реализовать...


                  Потом, я не говорю, что Postgres FTS может заменить ES во всех ситуациях. Я говорю, что множество раз видел ситуации, когда использовали ES там, где PostgreSQL хватает за глаза.

                    0

                    Просто интерсно есть ли смысл копать в этом направлении. С эластиком куча проблем, по сути только полтора человека из 15 с ним разбирается (и это нея :)), он у нас какой-то старой версии, а переезд на актуальную оценивается как сложный. А тут вот только-только переехали на Postgres с MySQL и может быть смысл поресичеть в этом направлении.

                      0

                      Если нагрузка высокая (много документов, частые поиски), то пытаться наверное не стоит. PostgreSQL классный и удобный, но довольно медленный. Во всяком случае был.


                      В highload лучше сразу SphinxSearch или ES или что-то еще использовать. Хотя до определенного предела его все же хватает, точно сказать, какая должна быть нагрузка, чтобы Postgres перестал справляться с FTS, не могу, давно это было.

                        0

                        У эластика есть собственные onsite курсы, которые за 2+2 дня позволят очень быстро втянуться в него. Либо же можно за 4+4 дня пройти тот же курс удаленно (вместо 8-часового треннинга в виртуальных классах используются 4-часовые). Если вам действительно нужно разбираться в решении, то пусть фирма выделит деньги на обучение сотрудников. Даже если вы после курсов поймете, что эластик не для вас, то это все равно будет лучше, чем копаться несколько месяцев и сделать те же выводы (только еще и с меньшей уверенностью).

                          0

                          Спасибо за наводку, недешево оно, конечно.

                            0

                            Я никакие курсы не проходил. Все по обрывкам документации, StackOverflow и бесконечные попытки написать сложный запрос. Такая была жизнь фрилансера. На одном фрилансерском проекте попросили написать очень сложный ES запрос, а я о нем ничего не знал. Через два или три дня все-таки сумел его написать, хотя он был огромный и сложно понимаемый.


                            В принципе, основы запросов в официальной доке неплохо описаны. А потом, уже отталкиваясь от этих запросов можно экспериментировать с написанием своих более сложных.


                            Прелесть ES в том, что с ней можно работать через браузер и командную строку (curl) — создавать индексы, наполнять их, писать запросы. Я этим постоянно пользуюсь при работе с ES. Например, два терминала рядом: в одном vim с текстом запроса, в другом — curl -XPOST -d @query.json http://localhost:9000


                            Но SphinxSearch в этом плане еще удобнее: он может работать по протоколу MySQL, и с ним можно взаимодействовать при помощи слегка нестандартных SQL запросов. В том числе, экспериментировать в командной строке используя стандартный клиет mysql.

                              0

                              Проблема не в написании запросов, а в эффективном их написании, а также правильной конфигурации кластера и решении проблем с ним. Вся информация доступна и так, но курсы её дают в сухом остатке. Банально экономят время (а это обычно деньги). К тому же есть у эластика и система сертификации, которую можно, конечно, пройти и без курсов, но тогда с реально большим опытом. За два-три дня самостоятельно — это прям совсем нереально для большинства. Сам сертификат — это, конечно, просто медалька, но процесс сдачи вскрывает кучу пробелов у сдающих, которые думали, что и так все знают.

              +2

              Да, интригу подняли, а на вопрос так и не ответили.

                0
                На самом деле, для полнотекстового поиска можно использовать сам Lucene, например, и не заморачиваться с распределенностью
                  0

                  В конечном итоге статья рассказывает, как добиться масштабируемости, но не говорит о том, нужна ли она вам.


                  И для первого шага создания поиска на Elastic начинать надо не с масштабирования, а определиться, что хотим искать, где хотим, какие фильтры накладывать, как будем пополнять индекс.

                0
                А что насчет бэкапов?
                В мире ES в принципе есть для этого инструменты?
                Или в подавляющем большинстве случаев (99.999%) elasticsearch используется для выгрузки данных из более привычных баз (postgres/mysql/mongodb) и если на датацентр, где располагается весь кластер, упадет метеорит и уничтожит все сервера вместе со всеми репликами, то всегда можно будет заново загрузить данные для поиска из оригинальных баз? Пусть это и может занять дни или недели, если базы громадные.
                  0

                  Да, ES предоставляет возможность бэкапов вот тут поподробнее

                    0
                    Если FS умеет, то можно делать снэпшоты на её уровне и просто копировать. Второй вариант — встроенное средство snapshot/restore, которое пишет пожатые копии индекса в папку, поддерживает инкрементальные обновления. Третий вариант — дампить сами объекты штуками вроде elasticdump, они в формате json. Последний вариант самый медленный.
                      0
                      А в реальных системах часто ли делают бэкапы? Везде где приходилось сталкиваться с elastic, его использовали для загрузки данных из других баз с целью как раз искать по этим данным. Насчет бэкапирования не в курсе, делали ли.
                        0
                        У нас в компании elastic — основная база данных, а не второстепенная. Объемы данных исчисляются в терабайтах. И да, бэкапы делаем, что-то пару раз в сутки, что-то вообще каждые полчаса-час.
                    0
                    ES Native если не ошибаюсь давно deprecated и с версии на версию выпилят совсем.
                      0
                      И кстати разделение нод по ролям совсем не обязательно. Вполне можно использовать псевдоодноранговый кластер без выделенных координаторов.
                        0

                        Для небольших и незагруженных кластеров вполне можно обойтись нодами с совмещенными ролями. В тексте нужно было сделать акцент о том, что ES позволяет разделением ролей разгружать узкие места.

                        0
                        Мы перепробовали все и Azure Search и Elastic и в итоге остановились на algolia.com
                        Когда пользователи начинают искать с летенси в 10мс у них глаза вылезают… Но опять же там есть свои нюансы.
                          0
                          Какие?
                            0
                            Ну как пример нельзя искать внутри *text*. Там есть методы чтобы это обойти но из коробки не получится. Ну и цена. В остальном — лучшее что с нами случилось в плане поиска. НО, самое приятное это из коробки генерация токена с зашитыми параметрами поиска. То есть можно очень легко сгенерить токен для юзера в котором например будет зашита роль или tenantId. И дальше каждый раз когда юзер будет что-то искать результаты уже будут отфильтрованы по этим параметрам.
                            0
                            Когда пользователи начинают искать с летенси в 10мс у них глаза вылезают…


                            Так эластик вполне быстро ищет. Нет?
                              0
                              ну не получалось меньше 300мс выдать что-то. минимальный индекс 60к 100к документов.
                                0
                                Интересно. Ну мы сами эластик не юзаем, только lucene. Он ищет в пределах 1-10 мс. Правда документов пока пару тысяч.
                                  0

                                  Вы, возможно, используете неоптимальную схему хранения данных (маппинг). Плюс потери могут быть не из-за эластика, а из-за установления ssl соединения (если вы его не держите постоянно открытым). Ещё, вполне возможно, что вы используете не оптимальный запрос с аггрегацией. В общем, скорее всего что-то вы делаете не так.

                                    0
                                    В этом и вся соль — слишком много «чего-то» не так может быть. У нас нет времени копаться.
                                    0
                                    0
                                  0
                                  Запятых в тексте сильно не хватает, не осилил
                                    +1
                                    Как бы мы не пытались оптимизировать структуры данных и алгоритмы поиска, когда речь заходит о действительно больших массивах данных и действительно большом количестве запросов, необходимо задуматься о возможности повлиять на производительность системы путем увеличения аппаратного ресурса.

                                    Не могли бы привести числа

                                    Master-ноды отвечают за важные, но довольно легкие общекластерные действия. Это означает, что они требуют большого ресурса и высокой стабильности от физической ноды.

                                    Если не затруднит,- внесите ясность

                                    p.s. Ваша статья изобилует оценочными. Хотелось бы больше конкретики.
                                      +2

                                      Я не решусь придумывать расчетные формулы, возможно они существуют. Но могу сказать, что многие цифры, которые встречаются в текстах Elastic были получены эмпирически. Касательно количества запросов и объема данных, здесь я пытался сказать, что эти цифры будут влиять на производительность кластера. Важно учитывать третью переменную — требуемое время выполнения. Например для пользовательского поиска я бы выжимал максимум скорости обработки. Т.е. важно отталкиваться от требований бизнеса в первую очередь.
                                      Касательно мастеров, важные и легкие действия это, например, отправка запросов на выделение шарда или его перемещение. Важные потому что от них зависит работоспособность кластера, а легкие потому что не требуют сложной обработки данных. В этом контексте слово "большой" не совсем уместно, я с вами согласен, правильней будет "достаточный", достаточность зависит от количества нод в кластере и количества шардов. Главное — избегать пиков нагрузки близких к максимуму для физической ноды. Надеюсь, я немного прояснил.

                                      +1
                                      Классная вещь, спасибо за статью! Но транзакций нету. А как же версия документов? Optimistic concurrency control? По моему один из главных аспектов ElasticSearch…
                                        +1

                                        Спасибо. Транзакции в ES — интересная тема для отдельной публикации, хочу написать об этом тоже. А касательно остального, старался выразить все максимально кратко концентрируясь на
                                        распределенности.

                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                      Самое читаемое