Почему APC увеличивает "Cache full count" для пользовательского кэша, хотя у него много доступной памяти?

Я играл с этим довольно долго, но я немного потерял, что делать. Я использую APC 3.1.3p1 для CentOs 5 с PHP 5.2.5. APC действует как кеш операционного кода, так и пользовательский кеш. В основном этот сервер запускает сайты Drupal 6, используя модуль CacheRouter для поддержки кеша APC. Я некоторое время запускал APC 3.0.19, но это заставляло Apache иногда блокироваться (документированная ошибка в этой версии APC), поэтому почему я на 3.1.3p1.

Я настроил APC на 512 Мбайт памяти (mmap).

Симптомы немного прерывисты, но, начиная с пустого кеша, это обычно то, что я вижу:

  • Пользовательский кеш заполняется довольно медленно. Несмотря на начальную скорость вставки примерно 20 000 вставок в секунду, кеш пользователя будет сообщать только несколько сотен, а затем несколько тысяч записей и будет расти очень медленно. Я могу, возможно, указать это на write_locking, но просто хочу упомянуть об этом, если это имеет важное значение для решения проблемы. Через несколько часов он достигает равновесия около 30 тыс. Записей.

  • Фрагментация начинается рано и быстро растет. В течение примерно 10 часов или около того я обычно на 100% фрагментации.

  • Общий объем использования кэша (opcode + user) стабилизируется примерно на 240 Мбайт или около того. Это практически никогда не будет превышать этот уровень. Через день или около того я начну видеть увеличение кеша кэша пользовательского кэша (UCCFC).

На момент написания этой статьи мой UCCFC находился на уровне 62358 и увеличивался, несмотря на то, что APC сообщал 280MB бесплатно. У меня есть user_ttl из 7200, но я также играл с настройкой на 0 или другие суммы, и это мало влияет на проблему.

Я подозреваю, что проблема имеет какое-то отношение к фрагментации. Сейчас мой сервер сообщает "Фрагментация: 100,00% (280,0 Мбайт из 280,0 Мбайт в фрагментах 24740)" и 280 МБ, так бывает, что это количество свободного пространства, которое сообщает APC; я думаю, совпадение. К сожалению, я нашел в документах или в других местах очень мало информации, чтобы указать, что именно означает "фрагментация" в мире APC, и, по-видимому, вы практически ничего не можете сделать, чтобы избежать этого.

Может ли кто-нибудь пролить свет на эту проблему?

Ответ 1

APC вычисляет процент фрагментации, используя следующую формулу:

(total_size_of_free_blocks_lt_5M / total_size_of_all_free_blocks) * 100

* Обратите внимание, что он считает только фрагменты размером менее 5M как фрагментированные.

Я переведу ваш конкретный случай на простой английский:

Фрагментация: 100,00% (280,0 Мбайт из 280,0 Мбайт в фрагментах 24740)

Это означает, что из 280M ваших свободных блоков все они меньше 5M. Если вы разделите свое свободное пространство на количество фрагментов, вы увидите, что это соответствует среднему размеру фрагмента ~ 11,6K.

Это означает, что если вы попытаетесь сохранить элемент, который больше всех доступных блоков, он не будет соответствовать, и произойдет одна из двух вещей, основанная на apc.user_ttl настройка конфигурации. Если TTL установлен в 0, то весь ваш кеш пользователя очищается и элемент вставлен. Если TTL установлен больше 0, то он будет вычеркнуть истекшие записи и вставить элемент. В обоих случаях общее количество кеша увеличивается. Наличие этого приращения в той мере, в какой оно есть в вашем случае, является индикатором того, что вы можете делать это неправильно.

Вот простая визуализация того, что фрагментация делает с вашим кешем с течением времени. Он представляет собой простой размер байтового 32 байта, каждый блок равен 1B.

[--------------------------------] (starts empty)
[A-------------------------------] (1B stored)
[ABB-----------------------------] (2B stored)
[ABBCCCC-------------------------] (4B stored)
... (time elapses)
[A--CCCC-EEE--GGGGGG-III--KKKLLLL]

Итак, теперь, если вы хотите сохранить элемент M, размер которого равен 4B, вы не можете, поскольку самый большой доступный блок - 2B. Это инициирует инкремент счетчика полного кеша и полный или частичный сброс на основе user_ttl, подробно описанный выше.

Теперь вопрос: это плохо в вашем случае?

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

  • Вы можете слишком много кэшировать; просто потому, что кеш там не означает, что вы должны засунуть в него все.
  • Вы можете кэшировать слишком короткий TTL (для записи), низкие TTL означают, что незаблокированные блоки освобождаются чаще.
  • Также возможно, что у вас есть несколько действительно больших предметов, которые вы пытаетесь сохранить. При 100% -ной фрагментации он гарантировал, что любой элемент >= 5М не будет соответствовать. Если ваш средний свободный размер блока составляет 11,6 тыс., То, скорее всего, данный элемент не поместится, так как размер его увеличивается до 11,6 тыс..

Возможно, вам захочется попробовать сортировать кеш пользователя по размеру и посмотреть, что такое ваши самые большие записи, и каковы их TTL. Может быть, они могут быть увеличены?

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