Каков наилучший способ кэширования сложных поисковых запросов в веб-приложении .NET? - PullRequest
2 голосов
/ 26 января 2012

У меня есть веб-сайт, который позволяет пользователям запрашивать определенные рецепты, используя различные критерии поиска.Например, вы можете сказать: «Покажите мне все рецепты, которые я могу сделать менее чем за 30 минут, которые будут использовать курицу, чеснок и макароны, но не оливковое масло».

Этот запрос отправляется на веб-сервер через JSON,и десериализован в объект SearchQuery (который имеет различные свойства, массивы и т. д.).

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

  1. Встроенный System.Web.Caching: Это обеспечит большой контроль над количеством элементов в кэше, когда ониистекает, и их приоритет.Однако кэшированные объекты обозначаются строкой, а не хеш-объектом.Мало того, что мне нужно было бы иметь возможность конвертировать SearchQuery объект в строку, но хеш должен быть идеальным и не вызывать никаких коллизий.
  2. Разработать мой собственный кэш InMemory: Что мне действительно нравится, так это Dictionary<SearchQuery, Results> объект, который сохраняется в памяти во всех сеансах.Так как результаты поиска могут начать становиться достаточно большими, я хотел бы иметь возможность ограничить количество запросов, которые будут кэшироваться, и предоставить способ истечения старых запросов.Что-то вроде очереди FIFO будет хорошо работать здесь.Я беспокоюсь о таких вещах, как безопасность потоков, и мне интересно, стоит ли здесь писать свой собственный кеш.

Я также изучал некоторые сторонние поставщики кеша, такие как NCache и Скорость .Оба они являются поставщиками распределенного кэша и, вероятно, полностью лишены того, что мне нужно в данный момент.Кроме того, кажется, что каждая система кеша, которую я видел, все еще требует, чтобы объекты были обозначены строкой.В идеале я хочу что-то, что удерживает кэш в процессе, позволяет мне задавать ключ по хэш-значению объекта и позволяет контролировать время и приоритеты истечения срока действия.

Буду признателен за любые советы или ссылки на бесплатные и желательнорешения с открытым исходным кодом, которые могли бы помочь мне здесь.Спасибо!

Ответы [ 4 ]

4 голосов
/ 26 января 2012

Исходя из того, что вы говорите, я рекомендую вам использовать System.Web.Caching и встроить его в слой DataAccess, экранирующий его от остальной части вашей системы. При вызове вы можете сделать запрос в реальном времени или извлечь из кэшированного объекта в зависимости от потребностей вашего бизнеса / приложения. Я делаю это сегодня, но с Memcached .

2 голосов
/ 26 января 2012

Кэш в памяти должен быть довольно прост в реализации.Я не могу придумать причину, по которой у вас должны быть особые опасения по поводу проверки уникальности объекта SearchQuery по сравнению с любым другим - то есть, хотя ключ должен быть строкой, вы можете просто сохранить исходный объект вместе с результатами.в кеше и проверяйте равенство сразу после того, как вы получили хэш.Я бы использовал System.Web.Caching для тех выплат, которые вы отметили (срок действия и т. Д.).Если случится столкновение, то второе будет просто не кэшироваться.Но это было бы крайне редко.

Кроме того, объем памяти, необходимый для хранения результатов поиска, должен быть тривиальным.Вам не нужно хранить данные каждого поля, каждой строки в полной детализации.Вам просто нужно иметь быстрый способ доступа к каждому результату, например, int первичный ключ.

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

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

2 голосов
/ 26 января 2012

Кратко рассмотрим библиотеку Enterprise Caching Application. Предполагая, что вам нужен широкий кеш веб-приложения, это может быть решением, которое вы ищете.

1 голос
/ 26 января 2012

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

Вы можете сгенерировать текст запроса из вашего объекта SearchQuery и использовать этот текст в качестве ключа для поиска с помощью System.Web.Caching.

Из краткого прочтения документации для класса Cache видно, что ключи должны быть уникальными - какими они были бы, если бы вы использовали их для запроса текста - не хеш ключа.

EDIT

Если вас интересуют длинные ключи кеша, проверьте следующие ссылки:

Длина ключа кэша в asp.net

Максимальная длина ключей кэша в объекте HttpRuntime.Cache?

Кажется, что класс Cache хранит кэшированные элементы во внутреннем словаре, который использует ключ hash . Ключи (текст запроса) с одинаковым хешем в конечном итоге попадут в одну и ту же корзину в словаре, где это просто быстрый линейный поиск, чтобы найти нужный при поиске в кэше. Так что я думаю, что вы будете в порядке с длинными цепочками ключей.

Кэширование asp.net довольно хорошо продумано, и я не думаю, что это тот случай, когда вам нужно что-то еще.

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