Можно ли использовать кеширование на объекте, который будет часто изменяться? Например, предположим, что у нас есть объект BlogPost, и есть столбец num_of_views (среди других), который часто изменяется. Возможно ли обновить поле num_of_views, как в кеше, так и в БД, без разрушения объекта кеша и его воссоздания? Я могу сделать это вручную, однако я беспокоюсь о проблемах с синхронизацией.
Да. Я не знаю, как вы делаете кеш, но вы можете в любой момент заменить экземпляр кеша:
public function updatePost($post_id, $num_of_views) { if (Cache::has('POST.'.$post_id)) { $post = Cache::get('POST.'.$post_id); } else { $post = Post::find($post_id); } $post->num_of_views = $num_of_views; $post->save(); Cache::put('POST.'.$post_id, $post); }
Нет, к сожалению, нет хорошего способа сделать это. Но позвольте мне объяснить …
Но на самом деле есть веская причина для этого – вся причина кэширования – ускорить процесс обслуживания нескольких статических данных. Например, WikiPedia обслуживает вас на 90%, потому что у нее так много пользователей. Статьи WikiPedia редко меняются, популярный – это означает, что кеширование – отличное решение для сохранения нагрузки на серверы.
В вашем случае вы хотели бы изменить кеш в основном каждый запрос, вы никогда не должны кэшировать счетчик просмотров, кстати, и это будет означать, что функциональность кэширования оказывается практически бесполезной. Даже с модификацией каждые 2, 3 или даже 10 запросов кэширование по-прежнему несколько бесполезно только потому, что не кеширование не регенерирует каждые несколько запросов, а вместо этого, чтобы сохранить загрузку с сервера.
Кэширование запроса на самом деле требует больше ресурсов, чем обычный запрос на обслуживание в реальном времени, поэтому вы можете себе представить, что кеширование таких переменных данных будет не только бесполезным, но и очень проблематичным для ваших серверов.
Другая проблема заключается в том, что вы предлагаете изменить только num_of_views, но сохранить остальную часть объекта в целости, но то, что вы не учитываете, заключается в том, что вы не можете на самом деле сделать это с помощью Cache. Они работают так: он сжимает любые данные, которые у вас есть, во что-то другое – это простой ключ «post_object_x» и значение, которое обычно представляет собой какую-то зашифрованную строку, такую как base64 или другие.
Это означает, что само поле num_of_views фактически не существует в самом кэше, если только вы его не расшифруете, а затем модифицируете и снова зашифруете, что так же быстро и ресурсоемким, как уничтожение и воссоздание объекта. Так что это просто невозможно с чисто технической точки зрения.
Надеюсь, вы могли понять, почему ваша идея не совсем подходит и почему также не самая лучшая идея в мире кэшировать любые счетчики когда-либо, если у вас нет массового сайта с миллиардами впечатлений, – и даже тогда вы должны сделать это только для очень высокий запрос рассчитывается специально и только короткие промежутки времени.
Существует несколько вариантов:
Отделите высокопроизводительные показатели от записи базы данных и обновите код модели Php, чтобы это отразить. По сути, ваша «модель», модель, которая делегирует свои сеттеры и геттеры другим моделям BlogSlowData и BlogFastData (я забыл название этого шаблона).
Вы меняете характер записи в базу данных. Так, например, когда вы обновляете запись, вы вставляете ее в очередь, которая обрабатывается быстро. Мне нравится использовать redis для этого, записи помещаются в очередь на redis, а затем другая программа считывает очередь и записывает ее в базу данных и в кеш.
Наконец, и, возможно, худший ответ. Можно ли использовать LUA-код Redis для записи обновленных показателей в базу данных или если вы используете mysql, вы можете использовать http://dev.mysql.com/doc/refman/5.6/en/innodb-memcached.html библиотеки memcache для интеграции данных непосредственно в вашу базу данных.
Вы также можете сделать комбинацию 1 и 2, в которой вы увеличиваете счетчики в redis и вставляете запись в очередь, указывая, что для BlogPost.id = 1234 требуется $ view с шагом в 1.
-daniel