Laravel-缓存频繁更新的Eloquent


Laravel - Caching Eloquent with Frequent Updates

是否可以对经常修改的对象使用缓存?例如,假设我们有一个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字段本身实际上并不存在于缓存本身中,除非您对其进行解密,然后对其进行修改并再次加密,这与销毁和重新创建对象一样快速且资源密集。因此,从纯粹的技术角度来看,这也是不可能的。


我希望你能明白为什么你的想法不太成功,为什么缓存任何计数器也不是世界上最好的主意,除非你有一个拥有数十亿次浏览量的大型网站——即使这样,你也应该只在很高的请求数和很短的时间内这样做。

有几个选项:

  1. 将高性能指标与数据库记录分离,并更新Php模型代码以反映这一点。实际上,您的"模型",一个将其setter和getter委托给其他BlogSlowData和BlogFastData模型的模型(我忘记了这个模式的名称)。

  2. 您可以更改对数据库的写入方式。因此,例如,当您更新一条记录时,您会将其弹出到一个队列中,该队列会得到快速处理。我喜欢使用redis,写入被排队到redis,然后另一个程序读取队列并将其写入数据库和缓存。

  3. 最后,也许是最糟糕的答案。您可以使用Redis的LUA代码将更新后的度量写入数据库,或者如果您使用的是mysql,则可以使用http://dev.mysql.com/doc/refman/5.6/en/innodb-memcached.htmlmemcache库将数据直接集成到数据库中。

你也可以做1&2,其中您递增redis中的计数器,并将一条记录推入队列,表明BlogPost.id=1234,需要$view递增1。

-daniel