Статьи

Solr + Hadoop = Big Data Love

Bixo Labs показывает, как использовать Solr в качестве решения NoSQL для больших данных.

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

С момента своего появления в 2006 году в рамках проекта по поиску веб- контента с открытым исходным кодом, компания Hadoop стала развиваться всеми возможными способами — пользователями, разработчиками, соответствующими проектами (так называемая «экосистема Hadoop»).

Примерно в то же время проект с открытым исходным кодом Solr стал наиболее широко используемым поисковым решением на планете Земля. Solr объединяет функциональность индексации и поиска на уровне API Lucene с API RESTful, графическим интерфейсом пользователя и множеством полезных функций администрирования и интеграции данных.

Интересная вещь в объединении этих двух проектов с открытым исходным кодом заключается в том, что вы можете использовать Hadoop для обработки данных, а затем обрабатывать их в Solr . И мы говорим не просто о свободном текстовом поиске; Solr может использоваться в качестве хранилища значения ключа (то есть базы данных NoSQL) благодаря поддержке запросов диапазона.

Даже на одном сервере Solr может легко обрабатывать многие миллионы записей («документы» на жаргоне Lucene). Более того, Solr теперь поддерживает сегментирование и репликацию благодаря новой передовой функциональности SolrCloud.

 

Фон

Я начал использовать Hadoop & Solr около пяти лет назад, в качестве ключевого элемента запуска поиска кода Krugle, который я стал соучредителем в 2005 году.

В то время Hadoop все еще был частью веб-сканера Nutch, который мы использовали для извлечения информации о проектах с открытым исходным кодом. А Solr был только что выпущен из духовки, только что был выпущен CNET как открытый исходный код.

В Bixo Labsмы используем Hadoop, Solr, Cascading , Mahout и многие другие технологии с открытым исходным кодом для создания пользовательских рабочих процессов обработки данных. Сеть является общим источником наших входных данных, которые мы сканируем, используя проект с открытым исходным кодом Bixo .

 

Эта проблема

Во время веб-сканирования состояние сканирования содержится в так называемой «базе данных сканирования». Для широких сканирований это должно работать с миллиардами записей, так как вам нужна одна запись для каждого известного URL. Каждая «запись» имеет URL-адрес в качестве ключа и содержит важную информацию о состоянии, такую ​​как время и результат последнего запроса.

Для искателей на основе Hadoop, таких как Nutch и Bixo, база данных обхода обычно хранится в наборе плоских файлов, где каждый файл представляет собой Hadoop «SequenceFile». Это просто упакованный массив сериализованных объектов ключ / значение.

Иногда нам нужно проверить эти данные, и вот здесь простая плоская структура файла создает проблему. Нет простого способа выполнить запросы к данным, но мы не можем сохранить их в традиционной базе данных, так как миллиарды записей + RDBMS == боль и страдания.

Вот где сияют масштабируемые решения NoSQL. Например, проект Nutch в настоящее время пересматривает этот слой DB для сканирования, чтобы разрешить подключение HBase, Другие варианты включают Cassandra, MongoDB, CouchDB и т. Д.

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

 

Архитектура

Так как же будет выглядеть такая система Hadoop + Solr?

Как упоминалось ранее, в этом примере наши входные данные поступают из CrawlDB веб-сканера Bixo, с одной записью для каждого известного URL. Но входные данные также могут быть файлами журналов или записями из традиционной СУБД или выходными данными другого рабочего процесса обработки данных.

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

 

Hadoop

Для непосвященных Hadoop реализует как распределенную файловую систему (также называемую «HDFS»), так и уровень выполнения, который поддерживает модель программирования с уменьшением карты.

Обычно данные загружаются и преобразуются во время фазы карты, а затем объединяются / сохраняются во время фазы сокращения. В нашем примере фаза карты считывает сжатые Hadoop файлы SequenceFiles, которые содержат состояние нашего веб-сканирования, а наша фаза сокращения — запись индексов Lucene.

В этой статье основное внимание уделяется не тому, как писать задания Hadoop Map-Reduce, но я действительно хотел показать вам код, который реализует всю суть работы. Обратите внимание, что это не типичный код манипуляции ключом / значением Hadoop, который болезненно писать, отлаживать и поддерживать. Вместо этого мы используем Cascading, который представляет собой API-интерфейс планирования и обработки данных с открытым исходным кодом, который создает задания Hadoop из более короткого и более представительного кода.

Приведенный ниже фрагмент читает SequenceFiles из HDFS и направляет эти записи в приемник (вывод), который сохраняет их, используя LuceneScheme, который, в свою очередь, сохраняет записи как документы Lucene в индексе.

Tap source = new Hfs(new SequenceFile(CRAWLDB_FIELDS), inputDir);
Pipe urlPipe = new Pipe("crawldb urls");
urlPipe = new Each(urlPipe, new ExtractDomain());

Tap sink = new Hfs(new LuceneScheme(SOLR_FIELDS,
STORE_SETTINGS,
INDEX_SETTINGS,
StandardAnalyzer.class,
MAX_FIELD_LENGTH),
outputDir,
true);
FlowConnector fc = new FlowConnector();
fc.connect(source, sink, urlPipe).complete();

Мы определили CRAWLDB_FIELDS и SOLR_FIELDS как набор элементов входных и выходных данных, используя такие имена, как «url» и «status». Мы пользуемся преимуществами схемы Lucene, которую мы создали для Cascading, которая позволяет нам легко отображать представление Cascading о мире (записи с полями) и индекс Lucene (документы с полями). У нас нет Каскадной Схемы, которая напрямую поддерживает Solr (разве это не удобно?), Но мы можем сделать это сейчас, так как мы можем сделать простой анализ для этого примера.

Мы проиндексировали все поля, чтобы мы могли выполнять запросы к ним. Только сообщение о состоянии содержит нормальный текст на английском языке, так что это единственный, который мы должны проанализировать (т. Е. Разбить текст на термины, используя пробелы и другие разделители токенов). Кроме того, операция ExtractDomain извлекает домен из поля URL и создает новое поле Solr, содержащее только домен. Это позволит нам выполнять запросы как к домену URL, так и к полному URL.

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

 

Запуск Hadoop Job

Для простоты и предоплаты сложно превзойти предложения Amazon EC2 и Elastic Mapreduce для выполнения заданий Hadoop. Вы можете легко раскрутить кластер из 50 серверов, выполнить свою работу, сохранить результаты и завершить работу — и все это без необходимости покупать оборудование или платить за ИТ-поддержку.

Существует много способов создания и настройки кластера Hadoop; для нас мы очень хорошо знакомы с (модифицированными) скриптами Hadoop EC2, которые вы можете найти в дистрибутиве Bixo. Пошаговые инструкции доступны по адресу http://openbixo.org/documentation/running-bixo-in-ec2/.

Код этой статьи доступен через GitHub по адресу http://github.com/bixolabs/hadoop2solr . README, отображаемый на этой странице, содержит пошаговые инструкции для построения и запуска задания.

После завершения работы мы скопируем полученный индекс из распределенной файловой системы Hadoop (HDFS) на главный сервер кластера Hadoop, а затем уничтожим одного ведомого, которого мы использовали. Теперь мастер Hadoop готов к настройке в качестве нашего сервера Solr.

 

Solr

Что касается Solr, нам нужно создать схему, которая соответствует индексу, который мы генерируем. В ключевом разделе нашего файла schema.xml мы определяем поля.

<fields>

<field name="url" type="string" indexed="true" stored="true" />

<field name="domain" type="string" indexed="true" stored="false" />

<field name="status" type="string" indexed="true" stored="true" />

<field name="statustime" type="string" indexed="true" stored="true" />

<field name="statusmsg" type="simpletext" indexed="true" stored="true" />

</fields>


Эти поля имеют однозначное соответствие с SOLR_FIELDS, который мы определили в нашем рабочем процессе Hadoop. Они также должны использовать те же настройки Lucene, которые мы определили в статических IndexWorkflow.java STORE_SETTINGS и INDEX_SETTINGS.

Как только мы это определили, все, что осталось, это настроить сервер, который мы можем использовать. Для простоты мы будем использовать единственный экземпляр EC2 в облаке Amazon (m1.large), который мы использовали в качестве нашего мастера для задания Hadoop, и запустим простой поисковый сервер Solr, который использует встроенный Jetty для предоставления контейнера webapp.

Аналогично заданию Hadoop, пошаговые инструкции приведены в README для проекта hadoop2solr на GitHub. Но в двух словах, мы скопируем и разархивируем настройки Solr 1.4.1 на сервере EC2, сделаем то же самое для нашей пользовательской конфигурации Solr, создадим символическую ссылку на индекс, а затем запустим его с:

 

Дать ему попробовать

Теперь начинается интересная часть. Поскольку мы открыли порт Jetty по умолчанию, используемый Solr (8983) в этом экземпляре EC2, мы можем напрямую получить доступ к удобной консоли администратора Solr, указав в браузере http: // <ec2-public-name>: 8983 / solr / admin

% cd solr

% java -Dsolr.solr.home=../solr-conf -Dsolr.data.dir=../solr-data -jar start.jar

Отсюда мы можем запускать запросы к Solr:

 

Мы также можем использовать curl для общения с сервером через HTTP-запросы:

curl http://<ec2-public-name>:8983/solr/select/?q=-status%3AFETCHED+and+-status%3AUNFETCHED

Ответ является XML по умолчанию. Ниже приведен пример ответа на вышеуказанный запрос, в котором мы нашли 2546 совпадений за 94 мс.

 

Теперь вот что я нахожу удивительным. Для индекса из 82 миллионов документов, работающих на довольно слабой коробке (EC2 m1.large = 2 виртуальных ядра), типичное время ответа на простой запрос, такой как «status: FETCHED», составляет всего 400 миллисекунд, чтобы найти 9M документов. Даже сложный запрос, такой как (состояние не FETCHED и не UNFETCHED), занимает всего шесть секунд.

 

пересчет

Очевидно, мы могли бы использовать более мощные коробки. Если бы мы переключились на что-то вроде m1.xlarge (15 ГБ памяти, 4 виртуальных ядра), то, скорее всего, мы могли бы обработать более 200 миллионов «записей» в нашем индексе Solr и все же получить разумное время отклика.

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

Совсем недавно в стволе Solr появилась поддержка SolrCloud . При этом используется проект с открытым исходным кодом ZooKeeper для упрощения координации нескольких серверов Solr.

Наконец, проект с открытым исходным кодом Katta поддерживает распределенный поиск на уровне Lucene со многими функциями, необходимыми для распределенного поиска производственного качества, которые еще не были добавлены в SolrCloud.

 

Резюме

Комбинация Hadoop и Solr позволяет легко обрабатывать большие объемы данных, а затем быстро обрабатывать результаты с помощью быстрого и гибкого API поиска и запросов. Поскольку Solr поддерживает запросы в стиле запросов, он подходит в качестве замены NoSQL для традиционных баз данных во многих ситуациях, особенно когда размер данных превышает разумный для типичной СУБД.

У Solr есть некоторые ограничения, о которых вам следует знать, в частности:

·      Обновление индекса лучше всего работает как пакетная операция. Отдельные записи могут быть обновлены, но каждая фиксация (обновление индекса) генерирует новый сегмент Lucene, который влияет на производительность.

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

·      Многие SQL-запросы не могут быть легко сопоставлены с Solr-запросами.

 

Код этой статьи доступен через GitHub по адресу http://github.com/bixolabs/hadoop2solr . README, отображаемый на этой странице, содержит дополнительные технические детали.