2012-02-05 3 views
6

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

Так что если я хочу иметь группу, называемую «статьями», и внутри этой группы у меня будут ключи, которые принимают форму идентификатора статьи, я не могу сделать это легко.

articles -> 5 -> cached data 
     -> 10 -> cached data 
     -> 17 -> cached data 

     ... 

Я мог бы предварить ключ с именем «группы», как:

article_5 -> cached data 
article_10 -> cached data 
article_17 -> cached data 

... 

Но это делает его невозможно удалить всю группу, если я хочу :(

A Рабочая решение будет состоять в том, чтобы хранить многомерные массивы (это то, что я делаю сейчас), но я не думаю, что это хорошо, потому что, когда я хочу получать/удалять кэшированные данные, мне нужно сначала получить всю группу. группа имеет один миллион статей в ней, вы можете представить, какой тип массива я буду итерации и se арки

Есть ли у вас лучшие идеи о том, как я могу достичь групповой вещи?


редактировать: нашел другое решение, не уверен, если это намного лучше, потому что я не знаю, насколько надежен пока. Я добавляю специальный ключ с именем __paths, который представляет собой в основном многомерный массив, содержащий полные префиксные пути ключей для всех остальных записей в кеше. И когда я запрашиваю или удаляю кеш, я использую этот массив в качестве ссылки, чтобы быстро узнать ключ (или группу ключей), который мне нужно удалить, поэтому мне не нужно хранить массивы и перебирать все ключи ...

ответ

18

Основываясь на своих наблюдениях, я смотрел на базовой реализации C модели кэширования APC «s (apc_cache.c), чтобы увидеть, что я мог бы найти.

Источник подтверждает ваши наблюдения, что в хранилище данных резервного хранилища нет никакой структуры группировки, так что любой свободно сгруппированный набор объектов должен выполняться на основе некоторого ограничения пространства имен или модификации самого уровня кэша. Я надеялся найти какой-то бэкдор, полагающийся на цепочку ссылок посредством связанного списка, но, к сожалению, кажется, что столкновения сверяются путем прямого перераспределения встречного слота вместо chaining.

Дальнейшая путаница этой проблемы, APC, похоже, использует явную модель кэша для пользовательских записей, не позволяя им стареть. Итак, the solution Emil Vikström provided, который опирается на модель LRUmemcached, к сожалению, не работает.

без изменения исходного кода самого APC, вот что я хотел бы сделать:

  1. Определение пространства имен ограничений, что ваши записи соответствовать. Как вы уже определили выше, это будет примерно как article_, добавленный к каждой вашей записи.

  2. список элементов в этом комплекте. Эффективно это будет 5, 10 и 17 схема, которую вы описали выше, но в этом случае вы можете использовать некоторый числовой тип, чтобы сделать это более эффективным, чем хранение большого количества строковых значений.

  3. Определить интерфейс для обновления этого набора указателей и примирил их с кэшем поддержки памяти, в том числе (как минимум) методы insert, delete и clear. Когда вызывается clear, пройдите каждый из ваших указателей, восстановите ключ, который вы использовали в хранилище данных резервного копирования, и очистите каждый из вашего кеша.

Что я защищаю для здесь вполне определенный объект, который выполняет операции, которые стремятся эффективно. Это линейно масштабируется с количеством записей в вашем кэш-кэше, но поскольку вы используете числовой тип для каждого элемента, вам понадобится более 100 миллионов записей или около того, прежде чем вы начнете испытывать настоящую боль в памяти при ограничении, например, несколько сотен мегабайт.


Тамас Imrei бить меня suggesting an alternate strategy я был уже в процессе документирования, но это имеет некоторые серьезные недостатки, которые я хотел бы обсудить.

Как определено в коде C подложки, APCIterator является линейной операцией времени, в течение полного набора данных при выполнении поиска (с помощью его конструктора public __construct (string $cache [, mixed $search = null ...]])).

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

/* {{{ apc_cache_user_find */ 
apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, \ 
    int keylen, time_t t TSRMLS_DC) 
{ 
    slot_t** slot; 
    ... 
    slot = &cache->slots[h % cache->num_slots]; 
    while (*slot) { 
     ... 
     slot = &(*slot)->next; 
    } 
} 

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

Удачи вам в применении.

+1

Хорошая работа! Я настоятельно рекомендую прочитать этот пост. –

+1

@ EmilVikström Спасибо! Я счастлив, что моя работа была проницательной. – MrGomez

4

Я имел эту проблему раз с Memcached, и я решил его с помощью номера версии в моих ключах, как это:

version -> 5 
article_5_5 -> cached data 
article_10_5 -> cached data 
article_17_5 -> cached data 

Просто измените номер версии и группа будет эффективно «ушел»!

memcached использует недавно применяемую политику для удаления старых данных, поэтому старая версия будет удалена из кеша, когда это необходимо. Я не знаю, имеет ли APC ту же функцию.


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

+0

APC не имеет политики LRU, но apc_add позволяет использовать TTL, Time To Live. Memcache был бы лучшим выбором в этом случае для такого рода данных, хотя из-за его LRU. –

3

Вы можете использовать APCIterator class, который, кажется, существует специально для таких задач, как это:

класса

APCIterator облегчает перебирать большие APC кэша. Это полезно, поскольку это позволяет Перебор больших кэшей шагов ...

1

К сожалению, APC не может этого сделать. Я очень часто хотел, чтобы это было возможно. Поэтому я искал альтернативы.

Zend_Cache имеет интересный способ сделать это, но он просто использует кеши для кэширования информации тегов. Это компонент, который, в свою очередь, может использовать бэкэнды (например, apc).

Если вы хотите пойти дальше, то вы можете установить Redis. У этого есть все, что изначально включено, и некоторые другие действительно интересные функции. Это, вероятно, самое чистое решение. Если вы смогли использовать APC, вы также можете использовать Redis.

Смежные вопросы