Найкращі практики впровадження користувальницького кешування?


17

Для кожного примірника кожного типу сутностей я генерую декілька кеш-пам'яток, названих на кшталт: [module_name]__[entity_type]__[entity_id]__[string_depending_on_where_the_cache_came_from]

Тепер, коли оновлюється сутність, я хочу скинути всі кеші, починаючи з відповідного типу і ідентифікатора.

Як я повинен зберігати / очищати ці кеші?

Наразі я просто cache_set () , але це створює проблему, коли я хочу очистити, оскільки я не знаю імен усіх відповідних кеш-пам'яток. Чи безпечно викидати записи кешу за допомогою db_delete ()?


Якщо ви не знаєте імен усіх відповідних кешів, як ви можете їх використовувати db_delete()?
kiamlaluno

Відповіді:


6

Щоб видалити записи з кеша, слід використовувати cache_clear_all () . Причина полягає в тому, що використовувана кеш-реалізація не могла використовувати таблицю бази даних в активній базі даних. Саме це відбувається з класом DrupalDatabaseCache , але це не повинно бути правдою для кожного класу.

Якщо ви подивитеся на _cache_get_object () (функція, яку викликають cache_get () та cache_set () ), ви помітите, що вона містить наступний код.

  static $cache_objects; 
  if (!isset($cache_objects[$bin])) {
    $class = variable_get('cache_class_' . $bin);
    if (!isset($class)) {
      $class = variable_get('cache_default_class', 'DrupalDatabaseCache');
    }
    $cache_objects[$bin] = new $class($bin);
  }
  return $cache_objects[$bin];

Клас для реалізації кешу може бути різним для кожного сховища скриньки кешів, і навіть типовий він може бути змінений.

Приватна система кешування статусу оновлення точно пояснює, чому нормальні функції кешу не використовуються в _update_cache_clear () , _update_cache_get () та _update_cache_set () . (Наголос мій.)

Ми спеціально НЕ використовуємо основний API кешу для збереження отриманих даних про доступні оновлення. Важливо, щоб цей кеш очищався лише тоді, коли ми його заповнюємо після успішного отримання нових доступних даних оновлення. Використання API кешу основного керування призводить до різного роду потенційних проблем, які призведуть до спроб постійно отримувати доступні дані оновлення, в тому числі, якщо на сайті визначено "мінімальний термін служби кешу" (який є як мінімальним, так і максимальним), або якщо веб-сайт використовує memcache або іншу підключається кеш-систему, яка передбачає летючі кеші.

Модуль Update Manager все ще використовує таблицю {cache_update}, але замість використання cache_set(), cache_get()і cache_clear_all(), є приватні допоміжні функції, які реалізують ті самі основні завдання, але забезпечують, щоб кеш не був передчасно очищений, і що дані завжди зберігаються в базу даних, навіть якщо використовується memcache або інший бекенд кешу.

Менеджер оновлень має конкретні потреби, які необхідні, оскільки спроба отримати інформацію про оновлення занадто часто може спричинити проблеми з серверами Drupal.org, враховуючи, що менеджер оновлення потенційно може отримати інформацію про оновлення з будь-якого сайту, на якому працює Drupal.

У вашому випадку ви можете використовувати [module_name]__[entity_type]__[entity_id]__[string_depending_on_where_the_cache_came_from]як ідентифікатор кеша для однієї сховища скриньки. У випадку, якщо вам потрібно видалити всі записи для юридичної особи, ви можете використовувати наступний код.

cache_clear_all("{$module}__{$entity_type}__{$entity_id}__", $bin, TRUE);

Якщо ви не можете отримати значення для присвоєння, $moduleколи ви очищаєте кеш, або ви хочете видалити запис кеша незалежно від модуля, для якого були кешовані дані, ви можете використовувати інший ідентифікатор кеша, наприклад [entity_type]__[entity_id]__[string_depending_on_where_the_cache_came_from], або [entity_type]__[entity_id]__[module_name]__[string_depending_on_where_the_cache_came_from]. cache_clear_all()видаляє всі записи кеша з ідентифікатором кеша, починаючи з рядка, переданого як аргумент, коли $wildcardє TRUE, а ідентифікатор кеша - ні '*'. У цьому випадку кеш буде очищено за допомогою наступного коду.

cache_clear_all("{$entity_type}__{$entity_id}__", $bin, TRUE);

8

Я не можу придумати належну причину, чому випадання записів вручну спричинило б проблему. Це, звичайно, передбачає, що ви використовуєте MySQL як допоміжний сервер для вашого певного кешу; хоча я думаю, що це стосується будь-якого іншого типу резервного кешу, метод очищення просто не обов'язково буде запитом до бази даних.

Якщо взяти за приклад модуль оновлення ядра, він обходить cache_*функції та очищає кеш вручну:

function _update_cache_clear($cid = NULL, $wildcard = FALSE) {
  if (empty($cid)) {
    db_delete('cache_update')
      // Clear everything except fetch task information because these are used
      // to ensure that the fetch task queue items are not added multiple times.
      ->condition('cid', 'fetch_task::%', 'NOT LIKE')
      ->execute();
  }
  else {
    $query = db_delete('cache_update');
    if ($wildcard) {
      $query->condition('cid', $cid . '%', 'LIKE');
    }
    else {
      $query->condition('cid', $cid);
    }
    $query->execute();
  }
}

Я завжди думаю, "якщо це достатньо добре для ядра, це для мене достатньо" :)

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.