Цель: Обеспечить непрерывность работы поиска по сайту с помощью Sphinx в момент проведения технических работ над одной из нод Sphinx кластера.
Sphinx отличный инструмент для организации поиска по сайту. В проекте в котором я участвую поиск объявлений происходит с помощью Sphinx. Объявления хранятся в бд в EAV модели а поиск по ним выполняет Sphinx затем объявления извлекаются по найденным сфинксом идентификаторам. Таким образом если Sphinx перестанет работать то это скажется на всём сайте.
Для работы используются rt индексы sphinx для моментального внесения изменений в поисковую выдачу если какое либо объявление будет отредактировано или забанено. Пока это работало на одной ноде всё было хорошо до тех пор пока не возникало необходимости внести изменения в саму структуру индексов. Для изменения списка атрибутов в поисковом индексе необходимо было править конфигурацию, перезапускать сфинкс и выполнять переиндексацию объявлений. Для того чтобы это производить без остановки работы сайта решено было построить кластер с одной главной нодой фактически выполняющей роль балансировщика и двумя дочерними нодами содержащими индекс и являющимися зеркальными между собой.
indexer
{
}
searchd
{
listen = 127.0.0.1:3301 # Порт для Sphinx Api
listen = 127.0.0.1:3309:mysql41 # Порт для SphinxQL
log = ./sphinx-log-searchd.log
query_log = ./sphinx-log-query.log
pid_file = ./sphinx-log-searchd.pid
binlog_path = ./sphinx-binlog
read_timeout = 5
max_children = 30
max_matches = 1000
seamless_rotate = 1
preopen_indexes = 0
unlink_old = 1
workers = threads
}
Для организации поискового кластера в Sphinx есть distributed индексы.
На главной ноде все индексы имеют следующий вид.
index distributed_section_1
{
type = distributed
agent = 127.0.0.1:9301:rt_section_1|127.0.0.1:9302:rt_section_1
ha_strategy = nodeads
}
К слову есть разница между тем как описывать дочерние ноды, в предыдущем примере они описаны как зеркала, а в следующем они описаны как ноды хранящие две разные части одного индекса. Разница в том что в первом случае запрос select отправляется на одну из нод, а во втором примере select отправляется на все ноды и результат поиска от каждой из нод объединяется.
index distributed_section_1
{
type = distributed
agent = 127.0.0.1:9301:rt_section_1
agent = 127.0.0.1:9302:rt_section_1
ha_strategy = nodeads # стратегия распределения запросов между нодами. nodeads - отправляет запросы к не мёртвым нодам
}
На дочерних нодах индексы описываются, как самые обычные real time индексы в Sphinx:
index rt_section_1
{
type = rt
mlock = 1
morphology = stem_en, stem_ru
min_word_len = 3
min_infix_len = 1
index_exact_words = 1
dict = keywords
path = ./notices_rt_section_1
rt_field = title
rt_field = text
rt_attr_uint = date
rt_attr_uint = active
rt_attr_multi = location
}
Всё с выборкой на кластере проблем нет.
mysql> select * from rt_section_1;
+---------+------------+--------+----------+
| id | date | active | location |
+---------+------------+--------+----------+
| 185191 | 1398749772 | 1 | 145430 |
| 185234 | 1398749771 | 1 | 145425 |
+---------+------------+--------+----------+
2 rows in set (0.03 sec)
Мне уже показалось что задача на этом решена, но не ту-то было. Выборка работает, а что на счёт REPLACE или INSERT запросов?
Как оказалось тут была засада — REPLACE и INSERT по умолчанию работают только на локальных индексах, а я использую распределенный.
Но не беда. Так как sphinx проект с открытым кодом я сделал свою сборку которая позволяет выполнять REPLACE запросы на distributed индексах.
Для её сборки надо скачать исходники и выполнить команду
cmake . && make
Теперь запустив эту сборку с точно теме же настройками что и ранее запрос выполнится на всех нодах-зеркалах.
mysql> REPLACE INTO rt_section_130054 (id, `location`, `title`, `text`, `active`, `date`) VALUES ( 2435558, ( 145411 ) , 'Тестовый заголовок', 'Тестовая запись', 1, '1399529047');
Query OK, 2 rows affected (0.04 sec)
Я для проверки использовал два зеркала, и мы видим что затронуто 2 записи, то есть по одной записи на каждой ноде.
This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.
Комментариев нет:
Отправить комментарий