キャッシュのクリアをフックする方法はありますか?


16

大きなキャッシュを備えた大きな教育機関のウェブサイトの場合、ユーザーがキャッシュ生成にアクセスできないように、できるだけ早くキャッ​​シュを生成したい...

私はいくつかの機能を実行し、重要なページを要求することでそれを行うcronセットをすべて持っていますが、私が探しているのはキャッシュがクリアされたときを知る方法、できればフックなので、これを起動できます生成関数。

何か案が ?


あなたが達成しようとしていることに応じて、ページの下にあるphayesの答えは、キャッシュがクリアされた後にコードを起動するための素晴らしいソリューションです。
レスターピーボディ

回答:


7

Drupal 7.xにはありませんが、十分な人々がそれを要求した後、これはDrupal 8.xのコアフックhook_rebuildとして追加されました。7.xでは問題を解決するより良い方法があるかもしれません-cronがキャッシュをクリアした直後に何らかの種類のキャッシュウォーミング機能を開始しようとしていますか?これにアプローチする別の方法は、Elysia cronを使用することです。Elysiacronは、cronの動作を大幅に改善していますが、ユースケースに関連する可能性のある2つは次のとおりです。

Elysia CronはDrupal標準cronを拡張し、各タスクをきめ細かく制御し、サイトにカスタムcronジョブを追加するいくつかの方法を可能にします。

  • 各cronタスクのタイミングと頻度を設定します(特定の時間に毎日いくつかのジョブを実行でき、その他は毎月のみなど)。タスクごとに、頻繁に使用するオプション(「1日1回」、「1日1回」...)を選択するか、強力な「Linux crontab」のような構文を使用して正確なタイミングを設定できます。頻繁に使用するオプションを定義して、サイトの構成を高速化することもできます。...
  • タスク実行の優先順位/順序を変更します。...

このモジュールを使用して、cronの実行方法をより細かく制御し、古いキャッシュの問題を解決できます。具体的には、再構築機能にフックをcronに追加し、Elysia cronを使用して、キャッシュクリア操作の直後にこれらの操作を実行するように設定できます。

また、cronの実行に問題があり、キャッシュが頻繁に再作成される可能性が高いようです。その場合、Elysia cronの特定のキャッシュクリア操作を他のcron操作とは異なるレートで実行するように設定できます。たとえば、検索インデックス作成は5分ごとに更新されますが、完全なキャッシュクリアはすべて実行されます6時間など

cronキャッシュ管理の微調整:drupal cronは、cronが実行されるたびに変数キャッシュを無効にします。これは、頻繁に呼び出されるタスクがある場合、パフォーマンス上の大きな問題です。Elysia cronはキャッシュ管理を最適化し、キャッシュを無効にする必要はありません。


まあこれは本当に残念です。急いでD8!実際、私はすでに述べたように、elysia_cronを使用してcronを1分ごとに実行し、必要なものを温めています。しかし、私のサイトの訪問数は1時間あたり1万回を超えるため、sbdyが空のキャッシュに落ちることは間違いありません。
グレゴリーカプスティン

11

いいえ、ありません。あんまり。少なくとも6または7ではありません。7と仮定すると:

あなたが見ていきます場合drupal_flush_all_caches()、あなたはそれを呼び出す表示されますhook_flush_caches()。このフックの目的は次のとおりです。

「キャッシュテーブル名をキャッシュテーブルのリストに追加します。キャッシュテーブルは、パフォーマンスページの[クリア]ボタンによって、またはdrupal_flush_all_cachesが呼び出されるたびにクリアされます。」

モジュールのフックを最後に置いてそこにコードを書くだけの魅力があるでしょう。しかし、もう一度見てみましょうdrupal_flush_all_caches()。実際の削除は次のように行われます。

  $cache_tables = array_merge(module_invoke_all('flush_caches'), $core);
  foreach ($cache_tables as $table) {
    cache_clear_all('*', $table, TRUE);
  }

これは、本当にクリアされる前にすべてのフックが起動されることを意味します。そこでは、実際の削除後に呼び出される唯一の機能がある_system_update_bootstrap_status()が、それは唯一の呼び出しをhook_boothook_exithook_watchdoghook_language_init-あなたはキャッシュクリアに依存する機能を提供するためにのみ実装しないフック。


くそー、これらすべてのリンクを追加するのに長い時間がかかりました;)なぜそれができないのを説明するのに多くの時間を費やした後、私は強制的に削除することはできないので、今のところそれを残します。
モウォ

3
それを残して、それは良い答えです。
mpdonadio

はい、それを残して、私はすべての良い答えをチェックすることはできませんが、私はそれを上げました:)
グレゴリー

11

これを行う方法はhook_flush_caches、と組み合わせて使用することregister_shutdown_functionです。サンプルコード:

/**
 * Implements hook_flush_caches().
 */
function mymodule_flush_caches() {
   // After caches are cleared we will run mymodule_cache_rebuild()
   register_shutdown_function('mymodule_cache_rebuild');

   // We don't want to add any custom cache-tables, so just return an empty array
   return array();
}

/**
 * Rebuild expensive cache items that need to be rebuilt immediately.
 */
function mymodule_cache_rebuild() {
  // Do the cache rebuild work here
}

を使用register_shutdown_functionすると、キャッシュがクリアされたにキャッシュ再構築関数が呼び出されます。hook_flush_caches決して使用されることを意図していない方法で悪用していますが、これはまさにあなたが必要とすることをするはずです。


8

ここで広範なストローク:

D8より前のバージョンにはフックがありませんが、標準的なデータベースに基づいて独自のデータベースバックエンドをDrupalDatabaseCache記述し、clear()関数にあらゆる種類のロジックを記述できます。簡単に見てみると、これはD7ではかなり単純であることが示唆され(クラスをカスタム名にコピーし、module_invoke_all()必要に応じてスローすることで変更するなど)、cache_backportモジュールを使用してもD6で動作します。次に、空にしたいキャッシュビンをクリアでポイントします。


3
これがおそらく最善の解決策です。複数のキャッシュビン(memcache、redisなど)がある場合、いくつかのキャッシュクラスを拡張する必要があるということだけが「問題」です。それでも価値がある
クライブ

memcached、apc、または他の非dbソリューションのキャッシュでは動作しませんか?
モウォ

私はRedisを使用していますが、それが機能するかどうかはわかりません。
グレゴリーカプスティン

drupal.org/project/redisを使用している場合は、カスタムモジュール内の提供されたクラスなどをコピーまたは変更して、代わりにそれらを使用することができます。ただし、パンテオンプラットフォームのラインに沿って、redisのすべての重いリフティングを提供するものを使用している場合は、はい、これらすべてについて調整する必要があります。
ジマジャンマ

3

とのソースを見るdrupal_flush_all_caches()clear_cache_all()、クリア後にフックが呼び出されないことがわかります。これはかなりのバグです。

ユーザーがキャッシュエントリの作成を待つ必要がないことを保証することは非常に難しいため、可能な限りキャッシュの完全なクリアを避けるようにしています。

実際に役立つ方法の1つは、パフォーマンスページを変更して、フォワードキャッシュをクリアし、メニュー、レジストリ、および同様のコアキャッシュに触れない送信ハンドラーを接続することです。メニューとレジストリの再構築は、キャッシュ全体の再構築に約半分の時間を要するため、これで良い結果が得られました。

もう1つは、drupal_http_request()すべてのURL(重要なURLだけでなく)を処理するブラシスクリプトを使用して、すべてがキャッシュされるようにすることです。これがどのように行われるかは、サイトによって異なります。時々、公開されたノードをEFQして、そのようにURLを作成することができます。また、XMLサイトマップテーブルを照会してURLを取得することもできます。その後、必要に応じてシステムcronからこれを呼び出します。


1

いくつかのオプション:
https : //www.drupal.org/project/cache_gracefulはまさにあなたが望むものです。

https://www.drupal.org/project/apdqcには、キャッシュクリアで起動する2つのフックがあり、クリアを変更drupal_alter('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);できるようにし、クリアに反応できるようにしますmodule_invoke_all('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);。APDQCが正常に動作するように$conf['apdqc_call_hook_on_clear'] = TRUE;し、settings.phpファイルに設定します。その後、キャッシュのクリアが完了するたびにフックを呼び出す必要があります。


1

これはすべての人に適しているわけではなく、次のページの初期化でのみトリガーされるため、OPに十分な速さではありません。ただし、時間に依存しない「キャッシュをすべてクリア」した直後にコードをトリガーするのに役立ちました。

明らかにHOOK、独自のモジュール名に置き換える必要があります。

/**
 * Implements hook_init().
 */
function HOOK_init(){
  // if there is no cache_not_empty defined, define it 
  // and then trigger our cache cleared code
  if ( !cache_get('HOOK_cache_not_empty') ) {
    cache_set('HOOK_cache_not_empty', TRUE);
    foreach (module_implements('cache_cleared') as $module) {
      module_invoke($module, 'cache_cleared');
    }
  }
}

/**
 * Implements hook_cache_cleared().
 */
function HOOK_cache_cleared(){
  // do what you need here, in which ever module.
}

ターゲットにする必要のある特定のビンがある場合、キャッシュクリアの時点でビン全体が空になる限り、上記を変更してサポートすることができます。

hook_initキャッシュされていないページに対してのみ実行されます。完全なキャッシュクリアはキャッシュされたページがないことを意味するはずですが、これは問題を引き起こすべきではありません。ただし、Varnishのような外部キャッシュシステムはこのトリガーの邪魔になり、次の適切な要求がDrupalに戻ったときにのみ発生することを意味します。

また、キャッシュシステムによって(cache_setすべての同時ユーザーがを利用できるようになるタイミングに応じて)、特に多数のユーザーがいる場合、このフックが同時に複数回トリガーされる可能性があることに注意してください。


0

クライアントが「すべてのキャッシュをフラッシュ」ボタンを押したときに、DrupalとVarnishの両方のキャッシュをフラッシュしたいという同様のニーズがありました。そのためにそのメニュー項目をハイジャックしました。

これは、cronなどのキャッシュクリアにヒットしません-メニューリンク上にあります。

/**
 * Implements hook_menu_alter().
 */
function mymodule_menu_alter(&$items) {
  if (isset($items['admin_menu/flush-cache'])) {
    $items['admin_menu/flush-cache']['page callback'] =
      "_mymodule_custom_flush_cache";
  }
}

/**
 * Hijacks the "flush all caches" button in menu
 */
function _mymodule_custom_flush_cache() {
  /**
   * Clear varnish, or other logic here
   */
  admin_menu_flush_cache(); //Run the normal cache clearing stuff
}

Thx Travisですが、ユーザーが自発的にトリガーするだけでなく、明確なキャッシュをフックする方法を探しています。
グレゴリー

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.