как кешировать по многим параметрам - PullRequest
1 голос
/ 01 сентября 2009

Я работаю над поисковым приложением, которое использует форму с 16 опциями фильтра: 1 (выбрано) или 0 (не выбрано). Результат в виде JSON извлекается через AJAX с помощью запроса GET.

Строка запроса выглядит следующим образом:

filter_1 = 0 & filter_2 = 1 ... опущено ... & filter_16 = 1 & page = 20

Каждый результат поиска имеет как минимум 2 страницы, которые могут быть просмотрены пользователем.

Мой вопрос: как я могу кешировать результаты поиска на основе входного параметра? Моя первая идея состояла в том, чтобы md5 запросить параметры, а затем написать файл кэша, используя хэш в качестве имени файла.

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

Но это не очень хорошая идея из-за множества параметров поиска. Кэшированных файлов было бы достаточно много (16 * 16 ???), и поскольку приложение используется только несколькими пользователями, я сомневаюсь, что все возможные комбинации когда-либо будут кэшированы. И каждый результат содержит X страниц, поэтому каждая из этих страниц будет собственным файлом кэша (16 * 16 * X).

Какова была бы хорошая стратегия кэширования для такого приложения? Реально ли реализовать кеш?

Ответы [ 4 ]

1 голос
/ 01 сентября 2009

Поскольку все ваши параметры поиска являются флагами, которые могут быть 0 или 1, вы можете рассмотреть битовую маску.

Каждый из ваших фильтров будет представлять значение, равное 2:

$filter_1 = 1;
$filter_2 = 2;
$filter_3 = 4;
...
$filter_8 = 256;
...
$filter_16 = 65536;

Используя PHP побитовые операторы , вы можете легко сохранить все 16 значений фильтра в одном целом числе. Например, значение «257» может быть достигнуто только с помощью комбинации filter_1 и filter_8. Если пользователь выбрал filter_1 и filter_8, вы можете определить битовую маску, выполнив:

$bitmask = $filter_1 | $filter_8  //gives 257

Благодаря уникальной битовой маске, отображающей состояние всех ваших фильтров, вы можете просто использовать ее в качестве ключа кеша без дорогостоящих операций md5. Поэтому в этом случае вы должны сохранить файл с именем «257» в своем кэше.

Этот метод также дает вам простой инструмент для аннулирования вашего кэша, так как вы можете проверять новые и обновленные записи, чтобы определить, каким фильтрам они соответствуют, и удалять любой файл, в имени которого установлен этот "бит", т.е. if ( ((int)$filename) & $filter == $filter) unlink($filename);. Если в ваших таблицах происходит частая запись, это может привести к некоторым проблемам с производительностью при сканировании кэша, но это неплохой метод для приложений с большим объемом чтения.

Это подход, который я люблю использовать при работе с битами или флагами. Однако вы должны тщательно обдумать, действительно ли вам нужно такое кэширование. Если у вас всего несколько пользователей системы, действительно ли у вас будут проблемы с производительностью на основе нескольких поисковых запросов? Кроме того, MySQL имеет встроенное кэширование запросов, которое очень хорошо работает в приложениях с высоким уровнем чтения. Если ваши процедуры генерации страниц результатов дороги, то кэширование выходных фрагментов определенно может быть полезным, но если вы говорите только о микросекундах производительности для нескольких пользователей, это может не стоить этого.

1 голос
/ 01 сентября 2009

Зачем вам кеш?

Если приложение используется только несколькими пользователями, кеширование фактически может не потребоваться.

0 голосов
/ 01 сентября 2009

Сначала убедитесь, что вам действительно нужен кеш (как предложил Тоби).

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

$key = calc_key();

$result = $memcache->get($key);

if (!$result) {
  $result = get_data_from_db();
  /* cache result for 3600 seconds == 1 hour */
  $memcache->set($key, $result, 0, 3600);
}

/* use $result */
0 голосов
/ 01 сентября 2009

Учитывая требования, которые вы описываете (небольшое количество пользователей), мне кажется, что кэширование всех комбинаций кажется разумным. Если, конечно, кэширование не имеет смысла вообще. Сколько времени занимает типичный запрос? Поскольку вы говорите, что приложение будет использоваться только несколькими людьми, стоит ли его кешировать? Моя очень приблизительная оценка состоит в том, что если запрос в этом случае не займет несколько секунд, не беспокойтесь о кэшировании. Если оно меньше секунды и вы действительно не хотите, чтобы приложение было супер-отзывчивым, кэширование не требуется.

В противном случае, я бы сказал (опять же, учитывая небольшое количество пользователей), что кэширование всех комбинаций - это нормально. Даже если их было использовано очень большое количество, их по-прежнему не более 65536, и многие современные операционные системы могут легко обрабатывать тысячи файлов в каталоге (в случае, если вы планируете кэшировать в файлы). Но в любом случае было бы разумно ограничить количество элементов в кеше и регулярно очищать старые. Кроме того, я бы не использовал MD5, я бы просто объединял нули и единицы из ваших фильтров для ключа кэша (например, 0101100010010100).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...