Master-X
Форум | Новости | Статьи
Главная » Форум » Программинг, Скрипты, Софт, Сервисы » 
Тема: Redis предварительное кеширование php страниц в фоне
цитата
21/05/16 в 10:46
 S_Flash
php + redis
На сайте с сотню категорий, поиск по которым в базе перед отображением занимает до 10 секунд. Кешировать по стандартному редисовому TTL не очень хорошо, так как некоторые категории используются редко, что придаёт им состояние первого показа с долгой сборкой. + для не редких категорий какому-то сёрферу всё-равно будет доставаться участь "создателья кеша", взваливая на него ожидание поиска по базе и сохранение статики в редис.
Подскажите, по какому принципу организовать кешитрование, только так, чтоб страница обновлялась в фоне зарание? Исключаем первыепоказы. Например, страница уже есть в кеше, сёрфер переходит на неё, время менять страницу, сёрферу показывается старый вариант, страница прересобирается, и сохраняется в кеш для следующего показа сёрферам.
Может есть готовые решения, чтоб подсмотреть?
цитата
21/05/16 в 11:40
 xjam
можно качать все свои категории кроном самому. Скрипт крона может параллельно качать все категории которые берет из сайтмапы или базы напрямую.
цитата
21/05/16 в 12:04
 S_Flash


Типа бота, который проходит по всем "категориям" с определённым интервалом для пересоздания кеша?
Думал о подобном, но есть категории с ну очень редким посещением, получается, что на них будет тратиться ресурс для "не популярных" категорий. Хотелось бы оптимизировать и этот момент для более плавной нагрузки, следовательно крон не очень подходит. Надо как-то отталкиваться от переходов сёрферов..
цитата
21/05/16 в 12:24
 Mika
S_Flash писал:
На сайте с сотню категорий, поиск по которым в базе перед отображением занимает до 10 секунд.

Может для начала стоит разобраться почему поиск занимает так много времени, и нет ли возможности его ускорить (подтюнить конфиг БД, создать/переделать индексы, подправить запросы)?
цитата
21/05/16 в 15:06
 S_Flash
Mika писал:
Может для начала стоит разобраться почему поиск занимает так много времени, и нет ли возможности его ускорить (подтюнить конфиг БД, создать/переделать индексы, подправить запросы)?

Поиск идёт по текстовому полю. Поле индексировано. Колличество записей в базе около 100к, это как я понимаю решающий фактор. Поиск частично основан на предпочтениях юзера, т.е. критерии поиска не статичны, надо прогибаться пот тем, как уже после создаст запрос пользователь скрипта, что не даёт до конца оптимизировать сам запрос.
цитата
21/05/16 в 15:36
 Magistrator
S_Flash писал:
Поиск идёт по текстовому полю

facepalm.gif

sphinx
цитата
21/05/16 в 16:25
 S_Flash
Magistrator писал:
sphinx

Да, думал, но монгадб со sphinx интегрируется через какой-то костыль. Дело в том, что в базе нет числового индекса, который подошёл бы для sphinx.. + В монге есть свой тектовый поиск со своей текстовой индексацией.

+ UPD Заметил, что спустя 24 часа идентичные поисковые запросы стали работать быстрее на треть. ХЗ, сожет монге для индексации нужно время типа разогрев..
цитата
21/05/16 в 17:32
 Mika
S_Flash писал:
Да, думал, но монгадб со sphinx интегрируется через какой-то костыль. Дело в том, что в базе нет числового индекса, который подошёл бы для sphinx.. + В монге есть свой тектовый поиск со своей текстовой индексацией.

А ты FTS в монге точно готовишь как надо? Покажи запросы и их explain'ы.
цитата
21/05/16 в 17:50
 Magistrator
S_Flash писал:
Да, думал, но монгадб со sphinx интегрируется через какой-то костыль. Дело в том, что в базе нет числового индекса, который подошёл бы для sphinx.. + В монге есть свой тектовый поиск со своей текстовой индексацией.

+ UPD Заметил, что спустя 24 часа идентичные поисковые запросы стали работать быстрее на треть. ХЗ, сожет монге для индексации нужно время типа разогрев..


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

звучит и выглядит конечно криво, но реализуется буквально на раз, два, три.
а скорость с которой работает полнотекстовый поиск в сфинксе будет просто офигительная.
цитата
21/05/16 в 20:34
 S_Flash
Mika писал:
А ты FTS в монге точно готовишь как надо? Покажи запросы и их explain'ы.


создаю индекс
Код:
var_dump($collection->createIndex(array('Title' => 'text')));


выборка
Код:

$cursor = $collection->find(
   array( '$text' => array( '$search' => $str_searchQuery  /*, '$language' => 'none'*/ ) )
);


Magistrator писал:
звучит и выглядит конечно криво

звучит отвратительно!
цитата
22/05/16 в 13:27
 xjam
S_Flash писал:
получается, что на них будет тратиться ресурс для "не популярных" категорий. Хотелось бы оптимизировать и этот момент для более плавной нагрузки, следовательно крон не очень подходит. Надо как-то отталкиваться от переходов сёрферов..

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

Еще вариант сохранения результата в файловый кеш.
Можно заменить класс редиса на файловый кеш в коде (что бы не лопатить всё) и посмотреть на результаты.
Любая ОС кеширует в память часто используемые файлы и это автоматически избавляет от необходимости заполнять память редко используемыми данными.

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

Есть еще один вариант: поручить nginx кеширование уже готовых страниц. fastcgi_cache или proxy_cache.
Это если не нужно что бы каждый хит юзера попадал на скрипт, самый прозрачный способ, конфиг тривиален, могу скинуть.
цитата
22/05/16 в 13:37
 Mika
S_Flash писал:
создаю индекс
выборка
Код:

$cursor = $collection->find(
   array( '$text' => array( '$search' => $str_searchQuery  /*, '$language' => 'none'*/ ) )
);


Полезнее было бы посмотреть какие конкретно запросы ты строишь, а также что показывает explain

10 секунд для поиска по 100к записям (если это названия/дески роликов, а не поэмы какие-нибудь) - это явно какой-то косяк. Может там монге памяти не хватает банально? Такой вариант не рассматривался?

И если я правильно понимаю, то категории ты формируешь как раз из результатов текстового поиска по определенному запросу, так? Тут же явный оверхед виден. Почему нельзя категории определять для каждой записи (той же регуляркой) при ее добавлении, и потом поиск в монге делать непосредственно по нужной категории?
цитата
23/05/16 в 14:19
 S_Flash
Mika писал:
Полезнее было бы посмотреть какие конкретно запросы ты строишь, а также что показывает explain


1) На какую информацию обратить там внимание? Чтобы выборка была исключительно только по индексируемым полям?

2) Кстати все до единого поля, которые учавствуют в выборке\сортировке надо проиндексировать? Некоторые поля не в индексе, так как получается, что нужно индексировать все до единого..

3) Так же в базе есть поле - массив, сортировка нужна по его внутрненним значениям. Типа:

{_id:123, Title:'Some Title', Date:123 Sort:{Score:5, Peoples:4, LikeABoss:0}}

Т.е. иногда надо сортировать по Date (индексировано), а иногда по Sort.Score или Sort.Peoples ...
Date логично проиндексировано, а вот как быть с Sort? Будет ли толк если создать индекс по полю Sort (его состав может меняться в разных документах, что делает невозможным более глубокую индексацию)?
цитата
23/05/16 в 23:31
 Mika
S_Flash писал:
На какую информацию обратить там внимание? Чтобы выборка была исключительно только по индексируемым полям?

nReturned, totalKeysExamined, totalDocsExamined
Идеал - это когда nReturned совпадает с totalDocsExamined.
Вообще монговский полнотекстовый поиск достаточно примитивен. И если нужен качественный, то стоит рассмотреть вариант Magistrator'а.
По поводу остальных вопросов - экспериментируй.
цитата
23/05/16 в 23:33
 Ailk
индексы создаются исключительно под запросы. Если есть сортировка по полю сорт, то индекс нужен на него 100%. Но скорее всего это будет составной индекс к выборке какого-то основного поля(или нескольких полей, причем порядок очень важен). Если выборки нету по срезу дат(нужна для лога, например), то индекс на дату вообще не нужен. По айдишникам сортируй (праймори кей).
Вообще непомешало бы углубить знания по индексам в бд и почитать best practices.
цитата
24/05/16 в 13:17
 5hark
Свали все в Elasticsearch и используй его и для поиска и для вывода/аггрегации категорий.

Вот посмотри видео https://www.elastic.co/elasticon/tour/2015/seattle/finding-the-right…home-depot (возможно там запросит email и прочее, введи рандомные данные, видео бесплатно показывается без всяких регистраций). Как раз там категории, при этом в результатах поиска еще выводится сколько из результатов в какой категории найдено.

Цитата:
поиск по которым в базе перед отображением занимает до 10 секунд
Поиск по elastic search занимает миллисекунды. Там в разделе видео есть рассказ от Goldman Sachs как они сократили время сбора данных для отчетов с нескольких часов до нескольких минут https://www.elastic.co/elasticon/tour/2015/tokyo/elasticsearch-in-equity-finance
цитата
24/05/16 в 14:30
 S_Flash
1) А кто подскажет нужно ли индексировать поля монги, по которым проводится не сортировка а выборка. Например, нужно отсортировать базу по дате, но при этом выбрать ещё те документы, поле которых содержит Status = 'active', отобросив остальные. Т.е. будет ли полезным для оптимизации сделать Status индексом?

2) Так же бывает, что выборка не по одному признаку, а из массива. Есть два варианта '$in' - скормить ей массив нужных для выборки значений ( 'Status' => array('$in' => array('active', 'wait', 'idle')) ) и, второй, сделать для небольшого массива что-то типа
Код:

'$or' => array(
  'Status' => 'active',
  'Status' => 'wait',
  'Status' => 'idle'
)


Какой вариант быстрее и, опять же, надо ли индексировать поле Status для данного варианта?
цитата
25/05/16 в 07:53
 localhost
быстрый вариант - это запустить тот же wget в кроне и выдать ему файл со списком урлов и опцией --delete-after (чтобы не сохранял хтмл)

долгий вариант:
перенастроить my.cnf - добавить key_buffer, подкругить join_buffer_size,read_buffer_size, tmp_table_size, thread_stack и прочие параметры
перенести tmpdir на tmpfs
поставить какой-нибудь hiphop с временем жизни кеша скажем час-два
и жизнь глядишь наладится
цитата
25/05/16 в 15:48
 S_Flash
localhost: Посмотрю. Пока было достаточно того, что сама база крутилась на SSD
цитата
31/05/16 в 11:05
 localhost
S_Flash писал:
localhost: Посмотрю. Пока было достаточно того, что сама база крутилась на SSD


"опыт, сын ошибок трудных" показывает, что для нагруженных mysql критично не диск и память, а скорость работы CPU, как ни странно.
у меня ниибически тормозил сервер на dual xeon 5020, sql-запросов в секунду от силы 30-40, а любое лишнее теледвижение приводило к тому, что зависали sql-queries по нарастающей и load average забирался в район 30-40
перенес все на i7-2600 проц, память 16гиг, все просто ахрененно. по бенчмаркам 2600й в 8 раз быстрее чем тот ксеон. в стеке запросов ничего не застревает, все крутится быстро, жизнь налаживается.

бенчмарки смотрятся здесь
https://www.cpubenchmark.net/multi_cpu.html


Эта страница в полной версии