Архитектура Solr

Solr — это поисковая система, созданная на базе Apache Lucene и предоставляющая функции полнотекстового поиска и индексирования данных. Solr используется для создания быстрых и легко масштабируемых поисковых приложений, предназначенных для работы с большими наборами структурированных и полуструктурированных данных. Solr предоставляет расширенные функции поиска, такие как фасетирование (faceting), фильтрация, ранжирование по релевантности, подсветка результатов и другие.

Примеры использования Solr:

  • корпоративные решения для текстового поиска;

  • поиск и аудит логов;

  • поиск в сфере электронной коммерции с фасетированием и агрегацией.

Функции

Ниже описаны ключевые возможности Solr:

  • Высокопроизводительный поиск.

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

  • Мощные возможности поиска.

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

  • Фасетирование и фильтрация.

    Благодаря встроенному механизму фасетирования (faceting) Solr может агрегировать результаты поиска по полю, диапазону или по произвольному критерию. Это позволяет получать более информативные результаты поиска, что не только удобно, но и очень полезно в аналитике.

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

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

  • Гибкое управление схемой.

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

  • Интеграция.

    Solr предоставляет REST API, который является основным каналом для отправки запросов на индексирование и поиск. Для программного взаимодействия с ядром Solr используются такие инструменты, как Solr Cell, Apache Tika, SolrJ. В ADH сервис Solr сконфигурирован для работы с HDFS, что позволяет выполнять поиск по HDFS-хранилищу.

Режим SolrCloud

В ADH сервис Solr по умолчанию работает в режиме SolrCloud, то есть несколько серверов Solr, координируемые с помощью ZooKeeper, могут работать на разных хостах ADH как одно целое. Такой распределенный подход основан на шардах и репликах и обеспечивает отказоустойчивость, автоматическую масштабируемость и высокую доступность.

Компоненты

Ниже приведена высокоуровневая архитектурная схема Solr.

Архитектура Solr
Архитектура Solr
Архитектура Solr
Архитектура Solr

Основные концепции и компоненты Solr:

  • Документ (document). Основная единица информации в Solr, набор данных, описывающий какую-то сущность. Например, карточка товара в интернет-магазине с названием товара, ценой, описанием и так далее.

  • Поле (field). Документ может иметь одно или несколько полей, в которых содержится конкретная информация, например, цена товара. Поля могут хранить данные различных типов, например, числовые, текстовые, двоичные и так далее. Использование подходящих типов данных в схеме позволяет Solr быстрее выполнять поисковые запросы.

  • Индекс (index). Solr хранит все данные в индексе Lucene. Ядро Lucene использует инвертированный индекс в качестве структуры данных для хранения документов. Инвертированный индекс похож на индекс в конце книги, когда для каждого отдельного слова указан список страниц, где это слово упоминается. Хранение данных таким образом делает процесс индексирования чуть более затратным, однако позволяет быстрее выполнять поиск. Добавление документа в индекс называется индексированием. После индексирования документ становится доступным для поиска.

  • Коллекция (collection). Один или несколько документов, сгруппированных в единый логический индекс с использованием одной и той же конфигурации и схемы.

  • Шард (shard). Логическая партиция коллекции. Шарды имеют одну или несколько физических реплик (часть данных индекса) и распределены по узлам кластера для обеспечения отказоустойчивости.

  • Реплика (replica). Физическая копия шарда. Реплики повышают отказоустойчивость, предоставляя дополнительные копии данных, и улучшают масштабируемость, предоставляя дополнительное пространство для поиска.

Процесс выполнения

Ниже приведено пошаговое описание процесса обработки запросов индексирования/поиска движком Solr.

Запрос на индексирование

  1. Клиент отправляет запрос на индексирование компоненту Solr Server. Например:

    $ curl -X POST 'http://ka-adh-3.ru-central1.internal:8983/solr/test_collection/update?commit=true&' -H 'Content-Type: application/json' --data @transactions.json

    Документ transactions.json:

    [
      {
          "id": 1,
          "txn_id": "1",
          "acc_id": 1001,
          "txn_value": 75.0,
          "txn_date": "2026-01-02",
          "comment": "The first transaction."
      }
    ]
  2. Компонент Solr Server, получивший запрос, называется координатором. Координатор парсит тело запроса, определяет целевую коллекцию и генерирует ID документов.

  3. Координатор обращается к ZooKeeper для получения информации о состоянии кластера, включая список активных узлов Solr. Solr применяет функцию маршрутизации (хеширование) для определения шардов, в которые должны быть направлены документы из запроса.

  4. Определив целевые шарды, Solr запрашивает у ZooKeeper информацию о текущей реплике-лидере (leader replica) для каждого шарда. Если реплика-лидер неизвестна, ZooKeeper запускает процесс выбора лидера. Определив реплику-лидера, Solr имеет полную информацию о том, в какой шард должен быть направлен каждый отдельный документ.

  5. Solr отправляет документы в соответствующие шарды на разных хостах ADH. Когда документ достигает шарда, он обрабатывается UpdateRequestProcessorChain, где проходит валидацию, сопоставляется со схемой и ему присваивается версия.

  6. Перед изменением файлов индекса Lucene лидер-реплика записывает операцию обновления в лог транзакций (tlog). После этого операция обновления считается устойчивой, то есть ее можно повторить даже в случае сбоя Solr.

  7. Реплика-лидер информирует остальные активные реплики шарда об операции обновления данных. Реплики обновляют свои tlog-файлы и подтверждают получение новых документов.

  8. Как только реплика-лидер записала операцию обновления в лог и необходимое количество реплик-не-лидеров сделали то же самое, координатор возвращает пользователю ответ 200 OK. Однако на этом этапе документ еще не доступен для поиска, а в индекс Lucene пока не было внесено никаких записей (обновления в режиме, близком к реальному времени).

  9. Сразу после ответа пользователю Solr добавляет документы в буфер Lucene в памяти.

  10. Последним шагом является операция коммита, которая записывает сегменты Lucene на диск, и документы из запроса становятся доступными для поиска. Момент выполнения коммита определяется настройками Solr.

Поисковый запрос

  1. Клиент отправляет поисковый запрос с параметрами фильтрации и фасетирования компоненту Solr Server. Например:

    $ curl -X GET 'http://ka-adh-1.ru-central1.internal:8983/solr/test_collection/query?q=acc_id:1001&q.op=OR&indent=true&fq=txn_date:%5B2026-01-01T00:00:00Z%20TO%202026-01-31T23:59:59Z%5D'
  2. Компонент Solr Server, получивший запрос, называется координатором. Координатор парсит параметры запроса, загружает схему и типы полей.

  3. Координатор запрашивает у ZooKeeper состояние Solr-кластера, чтобы определить целевые шарды и доступные реплики.

  4. Solr отправляет подзапросы репликам для их параллельного выполнения. На каждой реплике выполняются следующие действия:

    • Каждое выражение фильтра fq обрабатывается, а результаты кешируются.

    • Выполняется основное выражение запроса.

  5. Solr выполняет фасетирование. Для этого анализирует кешированные результаты и вычисляет промежуточные значения фасетов. Затем координатор объединяет ответы от шардов, суммирует значения фасетов и в итоге получает окончательный результат.

  6. Координатор запрашивает соответствующие документы из индекса Lucene. Solr запрашивает поля из необходимых документов по ID и формирует окончательный ответ, например:

    {
      "responseHeader":{
        "zkConnected":true,
        "status":0,
        "QTime":28,
        "params":{
          "q":"acc_id:1001",
          "facet.field":"acc_id",
          "indent":"true",
          "q.op":"OR",
          "fq":"txn_date:[2026-01-01T00:00:00Z TO 2026-01-31T23:59:59Z]",
          "facet":"true",
          "_":"1768832698829"}},
      "response":{"numFound":1,"start":0,"maxScore":1.0,"numFoundExact":true,"docs":[
          {
            "id":"1",
            "txn_id":[1],
            "acc_id":[1001],
            "txn_value":[75.0],
            "txn_date":["2026-01-02T00:00:00Z"],
            "comment":["The first transaction."],
            "_version_":1854745967899705344}]
      },
      "facet_counts":{
        "facet_queries":{},
        "facet_fields":{
          "acc_id":[
            "1001",1]},
        "facet_ranges":{},
        "facet_intervals":{},
        "facet_heatmaps":{}}}
Нашли ошибку? Выделите текст и нажмите Ctrl+Enter чтобы сообщить о ней