我应该在Memcache中存储数组或单个项目吗?

时间:2011-05-29 08:44:06

标签: memcached

现在我们在Memcache上存储一些查询结果。在调查了一下后,我发现许多人在Memcache中保存了每个项目。这样做的好处是,他们可以在任何其他请求中从Memcache获取这些项目。

存储数组

$key = 'page.items.20';
if( !( $results = $memcache->get($key) ) )
{
    $results = $con->execute('SELECT * FROM table LEFT JOIN .... LIMIT 0,20')->fetchAll();
    $memcache->save($results, $key, 3600);
}
...

优点:

  • 更容易

CONS:

  • 如果我更改单个项目,我必须删除所有缓存(这可能会很痛苦)
  • 我可以有重复的结果(不同查询中的相同项目)

VS

存储每个项目

$key = 'page.items.20';
if( !( $results_ids = $memcache->get($key) ) )
{
    $results = $con->execute('SELECT * FROM table LEFT JOIN .... LIMIT 0,20')->fetchAll();

    $results_ids = array();
    foreach ( $results as $result )
    {
        $results_ids[] = $result['id'];
        // if doesn't exist, save individual item
        $memcache->add($result, 'item'.$result['id'], 3600);
    }

    // save results_ids 
    $memcache->save($results_ids, $key, 3600);
}
else
{
    $results = $memcache->multi_get($results_ids);
    // get elements which are not cached
    ...
}
... 

优点:

  • 我没有在Memcache上存储两次相同的项目
  • 更容易使多个查询的结果无效(只是我们更改的项目)

CONS:

  • 更复杂的业务逻辑。
你怎么看?每种方式还有其他PROS或CONS吗?

一些链接

3 个答案:

答案 0 :(得分:1)

抓取统计数据并尝试计算命中率或可能的改进,如果您缓存完整查询与在MC中执行单个项目抓取。分析这种代码对于实际了解你的理论如何应用也非常有帮助。

这取决于查询的作用。如果您有一组用户,然后想要与其中一些朋友一起获得“十大音乐亲和力”,那么同时拥有这两个用户是值得的: - 每个朋友(事实上,网站的每个用户) - 每个用户的前10个查询(空间比CPU时间便宜)

但一般来说,值得在MC中存储将要经常使用的所有单个实体(在相同的代码执行中,或在后续请求中或由其他用户)。然后像CPU或资源繁重的查询和数据处理之类的事情要么是MC-it,要么将它们委托给异步。工作而不是实时工作(例如,十大网站用户不需要实时,可以每小时或每天更新)。 当然,考虑到如果您存储和MC个别实体,您必须从数据库中删除所有参照完整性,以便能够单独或成组地重复使用它们。

答案 1 :(得分:0)

这个问题是主观的和有争议的......

这取决于您的使用模式。如果您经常按ID提取单个节点,请分别存储每个节点。

另外,请注意,在任何一种情况下,除了前20名之外,存储列表并不是那么有用。如果以这样的方式插入/更新/删除节点,使得top-20不再有效,可能最终需要冲洗下一个20,依此类推。

最后,请记住它是一个缓存。如果您正在使用缓存,那么如果您输出的数据略显陈旧,那么您就可以使基础语句没有什么大不了的。

答案 2 :(得分:0)

memcached将数据存储在特定大小的块中,如下面的链接中所述。

http://code.google.com/p/memcached/wiki/NewUserInternals

如果memcached中的数据分布很大,那么较大尺寸块的数量将会减少,因此最近最少使用的算法会将数据推出,即使它们的空间可用。块大小。最近最少使用的算法适用于各自的块。 您可以根据memcached中的数据大小分布来决定选择哪种实现。