maxru
МИФИст
И снова кеширование. (Кэширование, cache)
В заголовок добавил различные варианты написания слова "кеширование" для лучшего поиска.
Читаю книгу Шлосснейгла "Профессиональное программирование на PHP" и, соответственно, появляются вопросы.
Сейчас - это вопрос о кешировании.
Кеширование блоков данных.
Предположим, что класс Article инкапсулирует в себе данные об одной конкретной статье.
Предположим, что существуют методы выдачи этих данных. Сам класс НЕ работает с представлением статьи, он работает только с данными.
Предположим, что есть класс ArticleDecorator, отвечающий за форматирование и вывод данных (на какое устройство - не важно).
(Почему я так назвал эти классы и аспекты вывода содержимого на экран прошу не обсуждать. Классы - чисто гипотетические. Поэтому схему реализации
кеширования на более низком уровне пока обсуждать не будем)
У класса ArticleDecorator есть метод ArticleDecorator:
ecorate(Article $obj), который принимает экземпляр класса Article и возвращает,
предположим, html код.
Я вижу несколько способов кеширования:
В заголовок добавил различные варианты написания слова "кеширование" для лучшего поиска.
Читаю книгу Шлосснейгла "Профессиональное программирование на PHP" и, соответственно, появляются вопросы.
Сейчас - это вопрос о кешировании.
Кеширование блоков данных.
Предположим, что класс Article инкапсулирует в себе данные об одной конкретной статье.
Предположим, что существуют методы выдачи этих данных. Сам класс НЕ работает с представлением статьи, он работает только с данными.
Предположим, что есть класс ArticleDecorator, отвечающий за форматирование и вывод данных (на какое устройство - не важно).
(Почему я так назвал эти классы и аспекты вывода содержимого на экран прошу не обсуждать. Классы - чисто гипотетические. Поэтому схему реализации
кеширования на более низком уровне пока обсуждать не будем)
У класса ArticleDecorator есть метод ArticleDecorator:
ecorate(Article $obj), который принимает экземпляр класса Article и возвращает,предположим, html код.
Я вижу несколько способов кеширования:
- На уровне ArticleDecorator.
a) Внутри класса производить проверки и выдавать либо кешированный html, либо генерировать кеш заново.
b) Воспользоваться примерно таким алгоритмом (простейший случай, возможность отключения кеширования не рассматриваем):
PHP:if(!$cache->getCacheExists('произвольный_идентификатор')) { $cache->startCaching('произвольный_идентификатор'); // ob_start(); ...// необходимые действия c ArticleDecorator $cache->stopCaching('произвольный_идентификатор'); // ob_get_contents(); ob_end_clear(); } $cache->getCache('произвольный_идентификатор'); - На уровне Article.
a) Внутри класса производить проверки и кешировать данные статьи (то есть фактически кеширование запросов к БД).
b) Делать то же самое кеширование полей обьекта, только с внешней проверкой и дозагрузкой.
PHP:if(!$cache->getCacheExists('произвольный_идентификатор')) { ...// необходимые действия c Article (инициализация, запросы к БД) $cache->doCaching('произвольный_идентификатор', Article $article); }else{ $article_data = $cache->getCache('произвольный_идентификатор'); $article = new Article($article_data); /* Здесь подразумевается, что при попытке получения из экземпляра класса Article значения какого-либо поля этого класса происходит запрос к БД для получения этого значения только если оно == "" (т.е. получение даных происходит при появлении необходимости в этих данных)*/ } - Комбинации 1 и 2.
[/list=1]
Внутреннее кеширование мне не нравится из-за необходимости жестко привязывать структуру классов к классу, отвечающему за кеширование.
Внешнее кеширование мне не нравится из-за необходимости делать некоторые проверки, дополнительные условные операторы.
Однако бОльшим злом мне все-таки кажется "встроенное" кеширование.
Способы кеширования (с помощью встроенных средств PHP).
Вот тут есть несколько способов, которые опять же имеют свои достоинства и недостатки.- Плоские файлы.
Достоинства:
- простота реализации
Недостатки:
- необходимо следить за режимами доступа к файлу (блокировка во время записи)
- могут быть "битые" файлы (процесс записи был аварийно прерван)
- необходимо продумывать иерархию структуры кеширования, т.к. ростом количества файлов в одной "папке" начинает рости время доступа.
По этому поводу хотелось бы услышать рекомендации по наиболее быстрой реализации кеширования в плоских файлах (в основном по структуре
каталогов для хранения этих самых файлов).
Первый недостаток может быть устранен с помощью записи кеша во временный файл, затем unlink() старого файла кеша (при этом для
процессов уже получивших доступ это останется незаметным, они смогут читать данные из "несуществующего" файла) и переименования временного
файла в файл кеша.
- DBM-кеширование (Berkley DB)
Достоинства:
- высокая скорость чтения/записи
- возможность одновременной записи/чтения
- идеально подходит для хранения данных вида "ключ"->"значение"
Недостатки:
- Нет встроенных средств слежения за временем создания/изменения отдельных строк (проблема определить устарел ли кеш или нет).
По этому поводу хотелось бы услышать про то, как лучше отследить время последнего обновления кеша (сделать таблицу в другой БД, например MySQL, с timestamp'ом последней модификации???)
- Кеширование на основе общей памяти
Рассматривать не будем. (ИМХО только для крупных проектов на (виртуальных) выделенных серверах. А виртуальный хостинг - это максимум 64 мегабайта оперативной памяти.)
- Кеширование на основе cookie
Достоинства:
- экономия места на сервере (при большом количестве пользователей)
Недостатки:
- "засорение" канала передачи данных лишними данными
- ограниченные размеры
- целесообразно хранить только данные для конкретного пользователя
- проблемы с безопасностью (содержание может быть украдено)
[/list=1]
Мое мнение - надо использовать комбинированное кеширование.
Кеширование с помощью cookie, наверное, стоит использовать только для хранения пользовательских настроек (например язык сайта, регион, скин сайта и т.д.),PHP:if(!$plainCache->getCacheExists('произвольный_идентификатор')) { $plainCache->startCaching('произвольный_идентификатор'); // ob_start(); $article_decorator = new ArticleDecorator($article_object); if(!$objectCache->getCacheExists('другой_произвольный_идентификатор')) { $article_object = new Article(345); $article_object->getAllData(); // заполняем все поля класса из БД $objectCache->doCaching('другой_произвольный_идентификатор', $article); }else{ $article_data = $cache->getCache('другой_произвольный_идентификатор');// DBM-кеш $article = new Article($article_data); } $plainCache->stopCaching('произвольный_идентификатор'); // ob_get_contents(); ob_end_clear(); } $plainCache->getCache('произвольный_идентификатор');// кеш из плоского файла
которые хранятся еще и в БД. При этом данные шифровать симметричным алгоритмом.
Хотелось бы увидеть комментарии уважаемых форумчан по поводу этой портянки.
- Плоские файлы.
.