Значения APC случайно исчезают - PullRequest
1 голос
/ 17 декабря 2010

Я использую 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 в качестве расширения (PECL) под управлением PHP 5.3.

UPDATE: В комментариях ниже вы увидите людей, заявляющих, что APC не является постоянным и ему нельзя доверять. Но в моем случае код выполняется в одном запросе страницы между 15-50 мс. Разве я не смогу доверять БТРу так долго?

UPDATE: Похоже, что кэш содержит несколько записей с одним и тем же ключом, когда он должен содержать только один - значение перезаписывается при вызове 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 ]

5 голосов
/ 17 декабря 2010

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

4 голосов
/ 26 декабря 2010

Я постараюсь ответить на свой собственный вопрос из того, что я узнал.

Во-первых, как справедливо отметили многие люди.

APC is not persistent.

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

Я пришел к выводу, что есть некоторые правила или, вернее, ловушки, о которых нужно знать - многие все еще ускользают от меня.Использование API APC означает использование apc_fetch и apc_store, и то и другое может потерпеть неудачу или, как более правильно сказать, пропустить.И почему вы иногда получаете NULL, когда ожидаете, что тайна кроется в данных.

Вот некоторые случайные биты информации:

  • Если вы пытаетесь сохранить значение доTTL заканчивается, новая запись будет создана.Так что замедляйте запись или уменьшайте TTL.

Количество секунд, в течение которых запись в кеше может простаивать в слоте, если этот слот записи в кеше необходим другой записи.Если оставить это значение равным нулю, кеш APC потенциально может заполниться устаревшими записями, в то время как более новые записи не будут кэшироваться.- http://php.net/manual/en/apc.configuration.php

  • Поиграйте с apc.ttl и apc.user_ttl, пока не найдете то, что подходит вам - пока вы не увидите много попаданий, а не много записей.

  • apc_fetch и apc_store могут возвращать NULL по ряду причин, некоторые из которых упоминались выше, например, ttl, другой причиной может быть тайм-аут выборки ключа.Но дело в дизайне.Ожидайте этого.

Если вы мне нравитесь, я очень расстроен поведением APC, взгляните на эту статью, указанную мне scoates: http://phpadvent.org/2010/share-and-enjoy-by-gopal-vijayaraghavan.Это не даст вам много ответов, но некоторые базовые знания о дизайне кэша и, возможно, помогут мне немного облегчить тот факт, что я не одинок:)

В моем случае с проблемой пути к классам, описанной в моем вопросе,Я решил использовать локальную переменную для создания кеша, а затем, в конце, сохранить ее в кеше с помощью одного вызова apc_store.Это привело к увеличению количества попаданий и уменьшению количества записей в кеше на ключ - и мой код теперь работает быстро.

0 голосов
/ 11 июня 2012

APC является постоянным, но отдельным для каждого процесса apache.

PHP поддерживает отдельное хранилище APC CACHE для каждого процесса apache, что совершенно нормально, поскольку каждый процесс apache имеет свое собственное пространство памяти.

...