Ключевые группы с кешем APC - PullRequest
       2

Ключевые группы с кешем APC

6 голосов
/ 05 февраля 2012

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

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

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

         ...

Я мог бы поставить префикс ключа с именем "group", например:

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

 ...

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

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

У вас есть лучшие идеи о том, как я могу добиться успеха в группе?


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

Ответы [ 4 ]

18 голосов
/ 12 апреля 2012

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

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

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

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

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

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

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

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


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

Как определено в базовом коде 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;
    }
}

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

Удачи в вашем приложении.

4 голосов
/ 05 февраля 2012

Однажды у меня была эта проблема с memcached, и я решил ее, используя номер версии в моих ключах, например:

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

Просто измените номер версии, и группа фактически исчезнет!

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


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

3 голосов
/ 12 апреля 2012

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

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

1 голос
/ 13 апреля 2012

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

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

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

...