Реализация кэширования средствами Unity

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


Наступил момент, когда и я при разработке такого высоконагруженного приложения столкнулся с этой проблемой. И решил её достаточно просто и безболезненно с помощью Unity Application Block.

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

Создание атрибута

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

Код атрибута в общем-то стандартный за исключением наследования специального класса HandlerAttribute.

Далее нам нужно создать собственно перехватчик события вызова метода. Вот его код.

Как видим, этот атрибут наследует интерфейс ICallHandler и реализует метод Invoke этого интерфейса. Invoke вызывается непосредственно перед вызовом самого метода.

Разберём метод Invoke подробнее. Сначала идёт проверка кэша на наличие в нём результата выполнения метода с данным именем и данными аргументами и их значениями. Если значение найдено в кэше — оно возвращается из кэша. Иначе запускается выполнение метода и результат перед выходом из процедуры сохраняется в кэш, чтобы быть использованным при повторном вызове.

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

Собственно кэш

Далее приведена всего лишь одна из возможных реализаций кэша. Поясню, что в приведённом ниже примере в качестве главного контейнера испозуется Hashtable, в котором ключом служит имя метода, а значением — ещё одна Hashtable, которая в свою очередь содержит в качестве ключа список аргументов и их значений, а в качестве значения — результат выполнения этих методов.

Сделал я это из соображений производительности, а точнее скорости поиска по контейнеру.

Ниже класс, который производит очистку кэша, а также используется для сбора некоторой статистики его использования. При его создании запускается таймер, раз в минуту удаляющий устаревшие объекты из кэша. При очистке сначала идёт попытка получить доступ к контейнеру, и если это не удаётся — очередная очистка просто пропускается.

Вот собственно и всё решение. Статья получилось достаточно длинной. В ней я показал, как можно использовать возможности Unity чтобы быстро и безболезненно внедрить кэширование в вашем приложении, даже если вы изначально об этом и не задумывались. Результаты внедрения кстати превзошли самые смелые ожидания. Время выполнения некоторых методов, которые к тому же вызывались достаточно часто и создавали видимую нагрузку на БД, сократилось в сотни раз.


Похожие записи:

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля отмечены *