【问题标题】:Should I store an array or individual items in Memcache?我应该在 Memcache 中存储数组还是单个项目?
【发布时间】:2011-09-04 05:42:10
【问题描述】:

现在我们正在 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);
}
...

优点:

  • 更简单

缺点:

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

存储每个项目

$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 上存储两次相同的项目
  • 更容易使多个查询的结果无效(只是我们更改的项目)

缺点:

  • 更复杂的业务逻辑。

你怎么看?每种方式还有其他优点或缺点吗?

一些链接

【问题讨论】:

    标签: memcached


    【解决方案1】:

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

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

    但总的来说,值得在 MC 中存储所有将频繁使用的单个实体(在相同的代码执行中,或在后续请求中或由其他用户使用)。然后诸如 CPU 或资源繁重的查询和数据处理之类的事情要么 MC-them,要么将它们委托给 async。作业而不是使它们成为实时的(例如,前 10 名站点用户不需要是实时的,可以每小时或每天更新一次)。 当然,考虑到如果您存储和 MC 单个实体,则必须从数据库中删除所有引用完整性,以便能够单独或分组重用它们。

    【讨论】:

    • 谢谢!是的,计算命中是我们要做的事情,所以我们有更多的数据来决定。您是否存储实体或/以及 html 片段?
    • 取决于场景...如果渲染很昂贵,缓存所有内容可能会很有趣,但除了不应用的场景(例如客户端渲染)之外,与数据库访问相比,一般渲染既便宜又快速,便宜很多
    【解决方案2】:

    这个问题是主观的和争论的......

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

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

    最后,请记住它是一个缓存。如果您使用的是缓存,那么您的基本声明是,如果您输出的数据有点陈旧,这没什么大不了的。

    【讨论】:

    • 当然只针对不同查询的前N个。关于缓存,这取决于我们拥有的元素数量。例如,如果我们要求前 10 名,而我们只有 5 个;下次我添加新项目时,我希望该缓存过期,以便我可以显示 6(如果没有,用户会觉得出了点问题)。
    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2010-09-12
      • 2012-07-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-27
      相关资源
      最近更新 更多