Я полагаю, это будет зависеть от стоимости доступа к предметам, входящим в сам ETag.
Я имею в виду, что пользователь отправляет запрос на данный ресурс; это должно вызвать операцию извлечения в базе данных (или другую операцию).
Если поиск - это что-то простое, например, получение файла, то запрос статистики файла выполняется быстро, и нет необходимости нигде хранить: MD5 пути к файлу плюс время его обновления достаточно.
Если извлечение подразумевает запрос к базе данных, то это зависит от того, сможете ли вы разложить запрос без потери производительности (например, пользователь запрашивает статью по идентификатору. Вы можете получить соответствующие данные только из таблицы статей. Таким образом, "попадание" в кеш будет влечет за собой один SELECT для первичного ключа. Но «промах» кеша означает, что вам придется снова запросить базу данных, тратя впустую первый запрос - или нет - в зависимости от вашей модели).
Если запрос (или последовательность запросов) хорошо разложим (и полученный код можно поддерживать), я бы снова выбрал динамический ETag.
Если это не так, то большая часть зависит от стоимости запроса и общей стоимости обслуживания решения с сохраненным ETag. Если запрос является дорогостоящим (или вывод громоздкий) и INSERT / UPDATE мало, то (и, я думаю, только тогда) будет выгодно сохранить вторичный столбец (или таблицу) с помощью ETag.
Что касается промежуточного программного обеспечения для кеширования, я не знаю. Если бы у меня был фреймворк, отслеживающий все за меня, я бы сказал «действуйте» - промежуточное ПО должно заботиться и реализовывать перечисленные выше моменты. Если промежуточное ПО не зависит от реализации (маловероятно, если только это не вырезание и вставка ... что не является чем-то неслыханным), тогда будет либо риск того, что оно «скроет» обновления ресурса, либо, возможно, чрезмерная неудобство при вызове API очистки кеша после обновлений. Оба фактора должны быть оценены в сравнении с улучшением нагрузки, предлагаемым поддержкой ETag.
Не думаю, что в этом случае существует «серебряная пуля».
Изменить: в вашем случае разница между случаями A и B небольшая или даже отсутствует. Чтобы иметь возможность реализовать getUpdatedAt (), вам необходимо сохранить время обновления в модели.
В этом конкретном случае я думаю, что было бы проще и легче поддерживать динамический, явный расчет ETag (случай A). Затраты на извлечение возникают в любом случае, а явные затраты на вычисление - это затраты на вычисление MD5, что действительно быстро и полностью зависит от ЦП. На мой взгляд, преимущества в ремонтопригодности и простоте огромны.
Что касается частично связанного с этим примечания, мне приходит в голову, что в некоторых случаях (нечастые обновления базы данных и гораздо более частые запросы к той же базе) может быть выгодно и почти прозрачно реализовать глобальное Last-Modified
время для всей базы данных . Если база данных не изменилась, то ни один запрос к базе данных не может возвращать различные ресурсы, независимо от того, что это за запрос. В такой ситуации нужно всего лишь сохранить глобальный флаг Last-Modified
в каком-нибудь удобном и быстром извлекаемом месте (не обязательно в базе данных). Например
function dbModified() {
touch('.last-update'); // creates the file, or updates its modification time
}
в любом UPDATE/DELETE
коде. Ресурс затем добавит заголовок
function sendModified() {
$tsstring = gmdate('D, d M Y H:i:s ', filemtime('.last-update')) . 'GMT';
Header("Last-Modified: " . $tsstring);
}
чтобы сообщить браузеру о времени модификации ресурса.
Затем любой запрос ресурса, включая If-Modified-Since
, может быть возвращен с помощью 304 без доступа к уровню постоянства (или, по крайней мере, с сохранением всего постоянного доступа к ресурсам). Время обновления на уровне записи не потребуется (не обязательно):
function ifNotModified() {
// Check out timezone settings. The GMT helps but it's not always the ticket
$ims = isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])
: -1; // This ensures the test will FAIL
if (filemtime('.last-update') <= $ims) {
// The database was never updated after the resource retrieval.
// There's no way the resource may have changed.
exit(Header('HTTP/1.1 304 Not Modified'));
}
}
Можно было бы разместить вызов ifNotModified () как можно раньше в маршруте предоставления ресурсов, sendModified как можно раньше в коде вывода ресурсов, а dbModified () везде, где база данных существенно изменяется в отношении ресурсов (т. Е. вы можете и, вероятно, должны избегать этого при регистрации статистики доступа к базе данных, если она не влияет на содержимое ресурсов).
person
LSerni
schedule
21.08.2012