![]() |
+7 (495) 229-0436 | ![]() |
shopadmin@itshop.ru | 119334, г. Москва, ул. Бардина, д. 4, корп. 3 | ![]() |
![]() |
![]() |
![]() |
|
|
Расширяем и улучшаем Cache в ASP.NET15.12.2009 15:02
Про ASP.NET-объект Cache наверняка знает каждый web-разработчик на платформе .NET. Совсем не странно, ведь это единственное решение для кэширования данных web-приложения в ASP.NET, доступное прямо из коробки. Синхронизация обновлений
Закэшированным данным, как и многому в нашем мире, со временем свойственно терять актуальность. Поэтому, по истечении отведенного интервала времени или при изменении одной из зависимостей, сохраненный элемент исчезнет из кэша, и нам придется положить его туда заново. MSDN расскажет нам, как это сделать, и мы напишем так:
Все выглядит правильно, но ровно до тех пор, пока мы не осознаем, что код может выполняться одновременно в нескольких потоках. И в этих нескольких строчках мы только что организовали классическое состояние гонки (race condition). Ничего страшного, конечно, не произойдет, просто элемент кэша будет обновлен несколько раз, и каждый раз для этого мы обратимся к базе данных. Но это лишняя работа, и ее можно избежать, применив обычную double-check блокировку. Вот так:
Таким образом, мы гарантируем, что только один поток отправится в базу данных за списком товаров, а остальные подождут его возвращения. Можно писать такой код всякий раз, когда мы работаем с кэшем, но лучше реализовать расширение объекта Cache при помощи extension-метода.
Итак,
Если в кэше нашелся элемент с заданным ключом, метод просто возвратит его, а в противном случае установит блокировку и выполнит загрузку. Конструкции
нужны для того, чтобы не получить такую же гонку при удалении элемента кэша в другом потоке. Теперь для получения нашего списка товаров мы можем написать только одну строку, а все остальное наше расширение возьмет на себя. Перегрузки можно добавить по вкусу :)
Итак, с одной задачей мы расправились, но есть еще кое-что интересное. К примеру, ситуация, когда необходимо объявить невалидными сразу несколько связанных элементов кэша. ASP.NET Cache предоставляет нам возможность создания зависимости от одного или нескольких элементов. Примерно так:
И при обновлении элемента parent элемент child будет удален. Пока ничего не напоминает? Что ж, еще немного кода, и у нас появится полноценная…
Поддержка тегов и групповой инвалидации
Подсистема тегирования будет работать вполне прозрачно, используя уже описанный механизм зависимостей от ключа в кэше. Такими ключами и будут - угадайте что? - теги. При добавлении в кэш элемента с некоторой коллекцией тегов мы создадим соответствующее количество ключей в кэше и зависимость от них.
Здесь в качестве значения версии тега я использую текущее время, как рекомендовалось в статье о Memcached , но в нашем случае сравнивать ничего не придется, этим займется ASP.NET. Теперь при добавлении элемента в кэш мы можем легко и просто создать зависимость от указанных нами тегов.
Осталось совсем немного - обеспечить сброс такой группы элементов в кэше. Для этого нужно всего лишь обновить элементы кэша, представляющие интересующие нас теги. Все остальное произойдет само собой.
Обратите внимание на то, что в методе, создающем зависимость от тегов, использовался метод
, а здесь -
. Существенная разница между этими в остальном очень похожими методами в том, что первый записывает информацию в кэш только в том случае, если указанный ключ не был создан ранее, а второй - записывает в любом случае, затирая старые данные. Это различие очень важно в нашем случае, потому что при простом добавлении элемента в кэш нам не нужно обновлять уже существующие теги.
На этом, кажется, и все…
Я требую продолжения банкета!
А продолжать тут еще есть куда. Например, можно доработать приведенный здесь метод Get так, чтобы вместо немедленного удаления данные кэша временно "переезжали" в другую ячейку, и вместо блокировки возвращать запрошенную информацию из нее, пока новые данные загружаются в кэш.
Можно вместо extension-методов сделать некую абстракцию провайдера кэширования и работать с любым хранилищем без изменения кода приложения или полностью отключать кэш при отладке, использовать IoC… да мало ли что!
И я надеюсь, что подходы, описанные в моей статье, окажутся полезными для вас ;) UPDATE : Посмотрев незамыленным глазом на собственный код, я узрел в нем одну нехорошую вещь - блокировка при синхронизации выставлялась на весь кэш целиком. Поэтому я изменил extension-метод Get с тем, чтобы он принимал пользовательский объект для блокировки. Ссылки по теме |
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
О нас |
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.
На протяжении многих лет интернет-магазин предлагает товары и услуги, ориентированные на бизнес-пользователей и специалистов по информационным технологиям. Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе. В нашем магазине вы можете приобрести лицензионное ПО выбрав необходимое из широкого спектра и ассортимента по самым доступным ценам. Наши менеджеры любезно помогут определиться с выбором ПО, которое необходимо именно вам. Также мы проводим учебные курсы. Мы приглашаем к сотрудничеству учебные центры, организаторов семинаров и бизнес-тренингов, преподавателей. Сфера сотрудничества - продвижение бизнес-тренингов и курсов обучения по информационным технологиям.
|
119334, г. Москва, ул. Бардина, д. 4, корп. 3 +7 (495) 229-0436 shopadmin@itshop.ru |
|
© ООО "Interface Ltd." Продаем программное обеспечение с 1990 года |