カスタムキャッシュを実装するためのベストプラクティス


17

あらゆる種類のエンティティのすべてのインスタンスに対して、次のような名前のキャッシュを多数生成します。 [module_name]__[entity_type]__[entity_id]__[string_depending_on_where_the_cache_came_from]

エンティティが更新されるたびに、関連するエンティティタイプとIDで始まるすべてのキャッシュを削除します。

これらのキャッシュを保存/消去するにはどうすればよいですか?

現在はcache_set()だけですが、関連するすべてのキャッシュの名前がわからないため、クリアしたいときに問題が発生します。db_delete()を使用してキャッシュエントリを削除しても安全ですか?


関連するすべてのキャッシュの名前がわからない場合、どのように使用できますdb_delete()か?
キアムルノ

回答:


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()、これらの同じ基本タスクを実装するプライベートヘルパー関数がありますが、キャッシュが早期にクリアされないようにし、データが常にmemcacheまたは別のキャッシュバックエンドが使用されている場合でも、データベース。cache_get()cache_clear_all()

Update ManagerはDrupalを実行しているサイトから更新情報を取得できる可能性があることを考慮して、更新情報を頻繁に取得しようとするとDrupal.orgサーバーで問題が発生するため、Update Managerには特定のニーズがあります。

あなたの場合、[module_name]__[entity_type]__[entity_id]__[string_depending_on_where_the_cache_came_from]単一のキャッシュビンストアのキャッシュIDとして使用できます。エンティティのすべてのエントリを削除する必要がある場合は、次のコードを使用できます。

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

あなたは値をに割り当てるために得ることができない場合は$module、あなたがキャッシュをクリアしているか、データがキャッシュされたモジュールから独立してキャッシュエントリを削除したいときは、次のような、異なるキャッシュIDを使用することができます[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]。isで、cache_clear_all()引数として渡された文字列で始まるキャッシュIDを持つすべてのキャッシュエントリを削除します。キャッシュIDはです。この場合、キャッシュは次のコードでクリアされます。$wildcardTRUE'*'

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();
  }
}

私はいつも「コアに十分なら、それは私に十分だ」と思う:)

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