Laravel — красноречивое кэширование с частыми обновлениями

Можно ли использовать кэширование на объекте, который будет часто изменяться? Например, допустим, у нас есть объект BlogPost, и есть столбец num_of_views (среди прочего), который часто изменяется. Можно ли обновить поле num_of_views как в кеше, так и в БД, не разрушая объект кеша и не воссоздавая его? Я могу сделать это вручную, однако я беспокоюсь о проблемах синхронизации.

1

Решение

Да, это. Я не знаю, как вы делаете кэш, но вы можете заменить экземпляр кэша в любое время:

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);
}
5

Другие решения

Нет, к сожалению, нет хорошего способа сделать это. Но позвольте мне объяснить …


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

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

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


Другая проблема заключается в том, что вы предлагаете изменить только num_of_views, но оставьте остальную часть объекта нетронутой, но вы не учитываете, что вы не можете сделать это с помощью Cache. Кеш работает так, что он сжимает любые ваши данные во что-то другое — это простой ключ ‘post_object_x’ и значение, которое обычно представляет собой какую-то зашифрованную строку, такую ​​как base64 или другие.

Это означает, что само поле num_of_views на самом деле не существует в самом кеше, если только вы не расшифруете, а затем не измените его и не зашифруете снова, что так же быстро и ресурсоемко, как уничтожение и воссоздание объекта. Так что это просто невозможно с чисто технической точки зрения.


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

2

Есть несколько вариантов:

  1. Отделите высокопроизводительные метрики от записи базы данных и обновите код модели Php, чтобы отразить это. По сути, ваша «модель», модель, которая делегирует свои установщики и получатели другим моделям BlogSlowData и BlogFastData (я забыл название этого шаблона).

  2. Вы меняете природу того, как вы пишете в свою базу данных. Так, например, когда вы обновляете запись, вы помещаете ее в очередь, которая быстро обрабатывается. Мне нравится использовать Redis для этого, записи ставятся в очередь в Redis, а затем другая программа читает очередь и записывает ее в базу данных и в кэш.

  3. Наконец, и, вероятно, худший ответ. Если вы можете использовать код Redis LUA для записи обновленных метрик в базу данных или если вы используете MySQL, вы можете использовать http://dev.mysql.com/doc/refman/5.6/en/innodb-memcached.html библиотеки memcache для интеграции данных непосредственно в вашу базу данных.

Вы также можете сделать комбинацию из 1 & 2, в котором вы увеличиваете счетчики в redis и помещаете запись в очередь, указывая, что BlogPost.id = 1234, требует $ view, увеличенное на 1.

-Даниил

1