APC值随机消失

时间:2010-12-17 08:32:42

标签: php apc

我正在使用APC将类名映射存储到类文件路径。我在自动加载功能中构建了这样的地图:

$class_paths = apc_fetch('class_paths');

// If the class path is stored in application cache - search finished.

if (isset($class_paths[$class])) {
    return require_once $class_paths[$class];

// Otherwise search in known places

} else {

    // List of places to look for class

    $paths = array(
        '/src/',
        '/modules/',
        '/libs/',
    );

    // Search directories and store path in cache if found.

    foreach ($paths as $path) {
        $file = DOC_ROOT . $path . $class . '.php';
        if (file_exists($file)) {
            echo 'File was found in => ' . $file . '<br />';

            $class_paths[$class] = $file;
            apc_store('class_paths', $class_paths);
            return require_once $file;
        }
    }   
}

我可以看到,随着越来越多的类被加载,它们被添加到地图中,但在某些时候apc_fetch在页面请求的中间返回NULL,而不是返回地图

Getting => class_paths
Array
(
    [MCS\CMS\Helper\LayoutHelper] => /Users/mbl/Documents/Projects/mcs_ibob/core/trunk/src/MCS/CMS/Helper/LayoutHelper.php
    [MCS\CMS\Model\Spot] => /Users/mbl/Documents/Projects/mcs_ibob/core/trunk/src/MCS/CMS/Model/Spot.php
)
Getting => class_paths
{null}

很多时候,缓存的值也会在页面请求之间消失。

这可能是什么原因?

我正在使用APC作为运行PHP 5.3的扩展程序(PECL)。

更新 在下面的评论中,您将看到人们声称APC不是持久性的,并且它不值得信任。但在我的情况下,代码在15-50ms之间的一个页面请求中执行。我不应该长期信任 APC吗?

更新 似乎缓存包含具有相同密钥的多个条目,当它应该只包含一个时 - 在调用apc_store()时覆盖该值。我希望这可以帮助别人理解这个问题。 (我已经禁用了强力防守并写锁定)

Array
(
    [num_slots] => 4099
    [ttl] => 0
    [num_hits] => 0
    [num_misses] => 3
    [num_inserts] => 9678
    [expunges] => 0
    [start_time] => 1293109072
    [mem_size] => 40064
    [num_entries] => 8
    [file_upload_progress] => 1
    [memory_type] => mmap
    [locking_type] => file
    [cache_list] => Array
        (
            [0] => Array
                (
                    [info] => fSchema::mysql::fORM::default::/Users/mbl/Documents/Projects/mcs_ibob/core/trunk/public_html/::::column_info
                    [ttl] => 0
                    [type] => user
                    [num_hits] => 0
                    [mtime] => 1293109072
                    [creation_time] => 1293109072
                    [deletion_time] => 0
                    [access_time] => 1293109072
                    [ref_count] => 0
                    [mem_size] => 12456
                )

            [1] => Array
                (
                    [info] => mcs:odk:class_paths
                    [ttl] => 3600
                    [type] => user
                    [num_hits] => 0
                    [mtime] => 1293109072
                    [creation_time] => 1293109072
                    [deletion_time] => 0
                    [access_time] => 1293109072
                    [ref_count] => 0
                    [mem_size] => 648
                )

            [2] => Array
                (
                    [info] => mcs:odk:class_paths
                    [ttl] => 3600
                    [type] => user
                    [num_hits] => 0
                    [mtime] => 1293109072
                    [creation_time] => 1293109072
                    [deletion_time] => 0
                    [access_time] => 1293109072
                    [ref_count] => 0
                    [mem_size] => 648
                )

            [3] => Array
                (
                    [info] => mcs:odk:class_paths
                    [ttl] => 3600
                    [type] => user
                    [num_hits] => 0
                    [mtime] => 1293109072
                    [creation_time] => 1293109072
                    [deletion_time] => 0
                    [access_time] => 1293109072
                    [ref_count] => 0
                    [mem_size] => 648
                )

            [4] => Array
                (
                    [info] => mcs:odk:class_paths
                    [ttl] => 3600
                    [type] => user
                    [num_hits] => 0
                    [mtime] => 1293109072
                    [creation_time] => 1293109072
                    [deletion_time] => 0
                    [access_time] => 1293109072
                    [ref_count] => 0
                    [mem_size] => 648
                )

            [5] => Array
                (
                    [info] => mcs:odk:class_paths
                    [ttl] => 3600
                    [type] => user
                    [num_hits] => 0
                    [mtime] => 1293109072
                    [creation_time] => 1293109072
                    [deletion_time] => 0
                    [access_time] => 1293109072
                    [ref_count] => 0
                    [mem_size] => 648
                )

            [6] => Array
                (
                    [info] => mcs:odk:class_paths
                    [ttl] => 3600
                    [type] => user
                    [num_hits] => 0
                    [mtime] => 1293109072
                    [creation_time] => 1293109072
                    [deletion_time] => 0
                    [access_time] => 1293109072
                    [ref_count] => 0
                    [mem_size] => 648
                )

            [7] => Array
                (
                    [info] => fSchema::mysql::fORM::default::/Users/mbl/Documents/Projects/mcs_ibob/core/trunk/public_html/::::merged_column_info
                    [ttl] => 0
                    [type] => user
                    [num_hits] => 0
                    [mtime] => 1293109072
                    [creation_time] => 1293109072
                    [deletion_time] => 0
                    [access_time] => 1293109072
                    [ref_count] => 0
                    [mem_size] => 23720
                )

        )

    [deleted_list] => Array
        (
        )

)

3 个答案:

答案 0 :(得分:5)

这不是持久性存储。 您可以通过增加APC的内存大小来改进它,但无论如何,没有任何保证。 因此,如果您看到它们被丢弃,您应该重新启动它们。

答案 1 :(得分:4)

我将尝试从我所学到的内容中回答我自己的问题。

首先,正如许多人正确指出的那样。

APC is not persistent.

如果没有实际的解释,或者更好的指导如何使用它,我很难接受这个声明。

我发现有一些规则或相当陷阱需要注意 - 很多人仍然没有找到我。使用APC API意味着使用apc_fetchapc_store这两个都可能失败,或者更正确地放置,错过。当你期望数据是神秘所在的时候,为什么你有时会收到NULL

以下是一些随机信息:

  • 如果您尝试在TTL用完之前存储值,则会创建一个新条目。因此减慢写入或减少TTL。
  

缓存条目的秒数   允许在插槽中闲置,以防万一   另一个需要缓存输入槽   条目。将此保留为零意味着   APC的缓存可能会填满   在较新的条目时使用过时的条目   不会被缓存。 -   http://php.net/manual/en/apc.configuration.php

  • apc.ttlapc.user_ttl一起玩,直到找到适合自己的内容为止 - 直到您看到很多点击而不是很多条目。

  • apc_fetchapc_store可以返回NULL,原因有很多,有些原因如上所述,例如ttl另一个原因可能是密钥提取超时。但重点是设计 - 围绕它。期待这一点。

如果你喜欢我一直对APC的行为感到非常沮丧,请看看这篇由scoates指出的文章:http://phpadvent.org/2010/share-and-enjoy-by-gopal-vijayaraghavan。它不会给你很多答案,但是有一些关于缓存设计的基本知识,或许像我一样,我并不孤单的一些事情:)

在我的问题中描述的类路径问题的情况下,我决定使用局部变量来构建缓存,然后在最后通过一次apc_store调用将其存储在缓存中。这导致命中率上升,每个键的缓存条目下降 - 我的代码现在运行得很快。

答案 2 :(得分:-2)

APC是持久的,但每个apache进程都是独立的。

PHP为每个apache进程建立一个单独的APC CACHE存储,这是完全正常的,因为每个apache进程都有自己的内存空间。