Ответ 1
На сайте электронной коммерции, над которым я работаю, мы используем Solr для быстрой аранжировки и поиска каталога продуктов. (В терминах, отличных от Solr, это означает, что стиль навигационных ссылок "ATI Cards (34), NVIDIA (23), Intel (5)" можно развернуть по каталогам продуктов на таких сайтах, как Zappos, Amazon, NewEgg и Lowe's.)
Это потому, что Solr предназначен для того, чтобы делать это быстро и хорошо, и попытка эффективно делать это в традиционной реляционной базе данных, ну, не произойдет, если вы не захотите начать добавлять и удалять индексы "на лету" и идут полным EAV, а это просто кашель Magento кашель глупый. Таким образом, наша база данных SQL Server является "авторитетным" хранилищем данных, а индексы Solr являются "проекциями" только для чтения этих данных.
Ты со мной до сих пор, потому что похоже, что ты в подобной ситуации. Следующим шагом является определение того, хорошо или нет, что данные в индексе Solr могут быть немного устаревшими. Вероятно, вы приняли тот факт, что он будет несколько устаревшим, но следующие решения:
- Насколько устаревший слишком устарел?
- Когда я могу оценивать скорость или запрашивать функции по сравнению с неподвижностью?
Например, у меня есть то, что я называю "Рабочим", который является службой Windows, которая использует Quartz.NET для выполнения С# IJob
реализации. Каждые 3 часа одно из этих заданий, которое выполняется, - это RefreshSolrIndexesJob
, и все, что делает это, - ping a HttpWebRequest
до http://solr.example.com/dataimport?command=full-import
. Это связано с тем, что мы использовали Solr встроенный DataImportHandler, чтобы фактически всасывать данные из базы данных SQL; работа просто должна "касаться" этого URL-адреса, чтобы синхронизировать работу. Поскольку DataImportHandler периодически фиксирует изменения, все это эффективно работает в фоновом режиме, прозрачно для пользователей веб-сайта.
Это означает, что информация в каталоге продуктов может задерживаться до 3 часов. Пользователь может щелкнуть ссылку на "Средний на складе (3)" на странице каталога (так как этот вид фасетных данных генерируется путем запроса SOLR), но затем см. на странице сведений о продукте, на которой нет доступных носителей (поскольку на этом страницы, информация о количестве является одной из немногих вещей, которые не кэшируются и не запрашиваются непосредственно в базе данных). Это раздражает, но, как правило, редко в нашем конкретном сценарии (мы достаточно малый бизнес, а не тот высокий трафик), и он будет исправлен через 3 часа в любом случае, когда мы снова восстановим весь индекс с нуля, поэтому мы приняли это как разумный компромисс.
Если вы можете принять эту степень "стойкости", то этот рабочий рабочий процесс - хороший способ. Вы можете использовать "перестроить все это каждые несколько часов" или ваш репозиторий может вставить идентификатор в таблицу, скажем, dbo.IdentitiesOfStuffThatNeedsUpdatingInSolr
, а затем фоновый процесс может периодически проверять эту таблицу и обновлять только те документы в Solr если перестраивать весь индекс с нуля периодически не разумно, учитывая размер или сложность вашего набора данных.
Третий подход заключается в том, чтобы ваш репозиторий создавал фоновый поток, который обновляет индекс Solr в отношении этого текущего документа более или менее одновременно, поэтому данные сохраняются только в течение нескольких секунд:
class MyRepository
{
void Save(Post post)
{
// the following method runs on the current thread
SaveThePostInTheSqlDatabaseSynchronously(post);
// the following method spawns a new thread, task,
// queueuserworkitem, whatevever floats our boat this week,
// and so returns immediately
UpdateTheDocumentInTheSolrIndexAsynchronously(post);
}
}
Но если это по какой-то причине взрывается, вы можете пропустить обновления в Solr, так что по-прежнему хорошая идея, чтобы Solr делал периодический "удалять все это и обновлять", или иметь фоновое изображение рабочего типа, которое проверяет для устаревших данных в Solr каждый раз в синей луне.
Что касается запроса этих данных из Solr, можно найти несколько подходов. Один из них заключается в том, чтобы скрыть тот факт, что Solr существует полностью с помощью методов репозитория. Я лично не рекомендую это, потому что вероятность того, что ваша схема Solr будет бессовестно адаптирована к пользовательскому интерфейсу, который будет получать доступ к этим данным; мы уже приняли решение использовать Solr для обеспечения легкой огранки, сортировки и быстрого отображения информации, чтобы мы могли использовать ее в полной мере. Это означает, что это явное в коде, когда мы хотим получить доступ к Solr и когда мы хотим получить доступ к обновленному объекту без кэширования.
В моем случае я в конечном итоге использую NHibernate для доступа к CRUD (загрузка ItemGroup
, futzing с его правилами ценообразования, а затем сохранение его обратно), переходя из шаблона репозитория, потому что я обычно не вижу его значения когда NHibernate и его сопоставления уже абстрагируют базу данных. (Это личный выбор.)
Но когда вы запрашиваете данные, я очень хорошо знаю, использую ли я его для целей, ориентированных на каталоги (я забочусь о скорости и запросах), или для отображения в таблице на внешнем административном приложении (я забочусь о валюта). Для запросов на веб-сайте у меня есть интерфейс под названием ICatalogSearchQuery
. Он имеет метод Search()
, который принимает SearchRequest
, где я определяю некоторые параметры - выбранные грани, поисковые термины, номер страницы, количество элементов на странице и т.д. - и возвращает SearchResult
- оставшиеся грани, количество результатов, результаты на этой странице и т.д. Довольно скучные вещи.
Интересно, что реализация этого ICatalogSearchQuery
использует список ICatalogSearchStrategy
под ним. Стратегия по умолчанию, SolrCatalogSearchStrategy
, попадает в SOLR напрямую через простой старомодный HttpWebRequest
и анализирует XML в HttpWebResponse
(который намного проще использовать, IMHO, чем некоторые из клиентских библиотек SOLR, хотя они возможно, улучшились с тех пор, как я последний раз смотрел на них больше года назад). Если по какой-либо причине эта стратегия выдает исключение или рвоту, то DatabaseCatalogSearchStrategy
напрямую попадает в базу данных SQL, хотя игнорирует некоторые параметры SearchRequest
, такие как огранка или расширенный поиск текста, поскольку это неэффективно для этого и это вся причина, по которой мы используем Solr. Идея состоит в том, что обычно SOLR быстро отвечает на запросы поиска в полнофункциональной славе, но если что-то взрывается и SOLR падает, тогда страницы каталога сайта могут по-прежнему функционировать в режиме ограниченной функциональности, нажимая базу данных с помощью ограниченный набор функций. (Поскольку мы сделали явным в коде, что это поиск, эта стратегия может принимать некоторые ограничения при игнорировании некоторых параметров поиска, не беспокоясь о том, что они слишком сильно влияют на клиентов.)
Key takeaway: Важно то, что решение о выполнении запроса относительно возможно устаревшего хранилища данных по сравнению с авторитетным хранилищем данных было сделано явным - если мне нужны быстрые, возможно устаревшие данные с расширенными функциями поиска, я использую ICatalogSearchQuery
. Если мне нужны медленные, обновленные данные с возможностью вставки/обновления/удаления, я использую NHibernate с именем query (или репозиторий в вашем случае). И если я вношу изменения в базу данных SQL, я знаю, что служба рабочего процесса вне процесса будет в конечном итоге обновлять Solr, что в конечном итоге будет согласовано. (И если что-то действительно важно, я мог бы транслировать событие или напрямую пинговать хранилище SOLR, сообщая ему обновить, возможно, в фоновом потоке, если бы мне пришлось.)
Надеюсь, это даст вам некоторое представление.