Apakah ada cara untuk menghubungkan kliring cache?

16

Untuk situs web institusi besar, dengan cache yang berat, saya ingin membuat cache sesegera mungkin, sehingga tidak ada pengguna yang dapat tiba di pembuatan cache ...

Saya memiliki cron set semua menit yang melakukannya, dengan menjalankan beberapa fungsi dan meminta halaman-halaman penting, tetapi apa yang saya cari adalah cara untuk mengetahui kapan cache baru saja dihapus , lebih disukai sebuah kait, jadi saya dapat meluncurkan ini menghasilkan-fungsi.

Ada ide ?

Gregory Kapustin
sumber
Bergantung pada apa yang Anda coba selesaikan, jawaban phayes di halaman tersebut adalah solusi yang bagus untuk memadamkan kode setelah cache dihapus.
Lester Peabody

Jawaban:

7

Tidak ada dalam Drupal 7.x tetapi ini ditambahkan sebagai hook inti, hook_rebuild di Drupal 8.x setelah cukup banyak orang memintanya. Namun, mungkin ada cara yang lebih baik untuk menyelesaikan masalah Anda di 7.x - Anda mencoba memulai beberapa jenis fungsi penghangat cache setelah cron membersihkan cache, betul? Cara lain untuk mendekati ini adalah dengan menggunakan Elysia cron yang memiliki sejumlah peningkatan signifikan pada bagaimana cron beroperasi tetapi dua yang mungkin relevan dengan use case Anda adalah:

Elysia Cron memperluas cron standar Drupal, memungkinkan kontrol butir halus atas setiap tugas dan beberapa cara untuk menambahkan pekerjaan cron khusus ke situs Anda.

  • Atur timing dan frekuensi setiap tugas cron (Anda dapat menjalankan beberapa pekerjaan setiap hari pada jam yang ditentukan, lainnya hanya bulanan dan seterusnya ...). Untuk setiap tugas, Anda cukup memilih antara beberapa opsi yang sering digunakan ("sekali sehari", "sebulan sekali" ...), atau gunakan sintaks yang mirip "linux crontab" untuk mengatur pengaturan waktu yang akurat. Anda bahkan dapat menentukan opsi yang sering Anda gunakan untuk mempercepat konfigurasi situs. ...
  • Ubah prioritas / urutan pelaksanaan tugas. ...

Anda dapat menggunakan modul ini untuk memiliki kontrol yang lebih baik atas bagaimana cron Anda berjalan untuk membantu menyelesaikan masalah cache basi. Khususnya, Anda bisa menambahkan hook ke fungsi rebuild Anda ke cron dan kemudian menggunakan Elysia cron, atur operasi ini untuk berjalan segera setelah operasi pembersihan cache.

Ini juga terdengar seperti Anda mungkin mengalami masalah dengan cron running yang sering menyebabkan cache terlalu sering dibuat ulang. Jika itu masalahnya, Anda dapat mengatur operasi pembersihan cache spesifik di Elysia cron untuk dijalankan pada tingkat yang berbeda dari operasi cron Anda yang lain, jadi misalnya pencarian indeks akan memperbarui setiap 5 menit tetapi cache penuh yang jelas hanya akan berjalan setiap 6 jam, dll.

Manajemen cache fine tune cron: drupal cron akan membuat cache variabel tidak valid setiap kali dijalankan, dan ini merupakan masalah kinerja yang hebat jika Anda memiliki tugas yang sering dipanggil. Elysia cron mengoptimalkan manajemen cache, dan tidak perlu membatalkan cache.

schnippy
sumber
Nah ini benar-benar mengecewakan. Cepat D8! Sebenarnya, saya sudah punya, seperti yang saya katakan, cron dengan elysia_cron, berjalan setiap menit, menghangatkan apa yang saya butuhkan. Tetapi karena situs saya akan memiliki> 10.000 / kunjungan / jam, saya cukup yakin sbdy akan jatuh pada cache kosong ... Lagipula, saya tahu sekarang bahwa ini adalah batasan D7!
Gregory Kapustin
12

Cara untuk melakukan ini adalah menggunakan hook_flush_cachesdalam kombinasi dengan register_shutdown_function. Kode contoh:

/**
 * 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
}

Menggunakan register_shutdown_functionberarti bahwa fungsi membangun kembali cache kita akan dipanggil setelah cache dihapus. Kami menyalahgunakan hook_flush_cachesdengan cara yang tidak pernah dimaksudkan untuk digunakan, tetapi ini harus melakukan apa yang Anda butuhkan.

phayes
sumber
Saya sangat suka solusi ini. Sebelum menggunakannya sendiri, saya mencari masalah / konflik yang diketahui menggunakan register_shutdown_function()Drupal, dan menemukan drupal_register_shutdown_function core Drupal () : "Wrapper untuk register_shutdown_function () yang menangkap pengecualian yang dilemparkan untuk menghindari" Pengecualian yang dilemparkan tanpa bingkai stack di Tidak Dikenal " . Saya tahu itu membuat saya merasa lebih baik abusing hook_flush_cachesjika saya hanya menggunakan fungsi inti Drupal untuk melakukannya
runswithscissors
11

Tidak, tidak ada. Tidak juga. Setidaknya tidak dalam 6 atau 7. Dengan asumsi 7:

Jika Anda akan melihat drupal_flush_all_caches()Anda akan melihatnya memohon hook_flush_caches(). Pengait ini dimaksudkan untuk:

"tambahkan nama tabel cache ke daftar tabel cache yang akan dihapus oleh tombol Hapus pada halaman Kinerja atau setiap kali drupal_flush_all_caches dipanggil."

Akan tergoda untuk hanya membuat hook modul Anda yang terakhir dan menulis kode di sana. Tapi mari kita lihat lagi drupal_flush_all_caches(). Penghapusan aktual terjadi seperti ini:

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

Ini berarti bahwa semua kait dilepaskan sebelum apapun benar-benar dihapus. Hanya ada satu fungsi yang disebut setelah penghapusan sebenarnya, _system_update_bootstrap_status()tetapi hanya panggilan hook_boot, hook_exit, hook_watchdogdan hook_language_init- kait Anda tidak ingin menerapkan hanya untuk menyediakan fungsionalitas cache-jelas tergantung.

Mołot
sumber
Sial, butuh waktu lama untuk menambahkan semua tautan ini;) Akan meninggalkannya untuk saat ini karena saya tidak bisa memaksa diri untuk menghapusnya, setelah begitu banyak waktu dihabiskan untuk menjelaskan mengapa itu tidak bisa dilakukan.
Mołot
3
Biarkan saja, itu jawaban yang bagus.
mpdonadio
Ya tinggalkan, saya tidak bisa memeriksa semua jawaban yang bagus tapi saya menaikkannya :)
Gregory Kapustin
8

Garis besar di sini:

Meskipun tidak ada hook di luar sana di pra-D8, Anda bisa menulis backend database Anda sendiri berdasarkan standar DrupalDatabaseCachedan kemudian menulis segala atau semua jenis logika ke dalam clear()fungsi Anda . Pandangan cepat akan menyarankan ini menjadi cukup mudah di D7 (cukup salin kelas ke nama kustom Anda dan memodifikasinya dll dengan melemparkan yang module_invoke_all()sesuai) dan dengan modul cache_backport bahkan akan bekerja di D6. Lalu tunjukkan tempat sampah yang ingin Anda bersihkan bersih-bersih dan Anda harus segera pergi.

Jimajamma
sumber
3
Ini mungkin solusi terbaik, hanya 'masalah' adalah bahwa jika Anda memiliki banyak tempat cache (memcache, redis, dll) Anda harus memperpanjang beberapa kelas cache. Namun masih layak
Clive
Tidak akan bekerja dengan cache di memcached, apc, atau solusi non-db lainnya, bukan?
Mołot
Saya menggunakan Redis, tidak yakin itu akan berhasil.
Gregory Kapustin
Jika Anda menggunakan drupal.org/project/redis, Anda harus dapat menyalin atau memodifikasi kelas yang disediakan dll dalam modul khusus dan kemudian menggunakannya. Namun, jika Anda menggunakan sesuatu di sepanjang platform Pantheon di mana mereka menyediakan semua pengangkat berat untuk redis, maka ya, Anda harus berkoordinasi dengan mereka tentang semua ini.
Jimajamma
3

Jika Anda melihat sumbernya drupal_flush_all_caches()dan clear_cache_all(), Anda akan melihat bahwa tidak ada kait yang dipanggil setelah pembersihan, yang merupakan bug bug yang cukup.

Sangat sulit untuk menjamin bahwa seorang pengguna tidak akan pernah harus menunggu beberapa entri cache dibangun, jadi saya mencoba untuk menghindari cache penuh sebanyak mungkin.

Salah satu metode yang benar-benar membantu adalah membentuk mengubah halaman kinerja untuk memasang pengatur pengiriman yang hanya membersihkan cache yang menghadap ke depan, dan tidak menyentuh menu, registri, dan cache inti yang serupa. Saya mendapatkan hasil yang baik dengan ini, karena membangun kembali menu dan registri memakan waktu setengah dari waktu untuk membangun kembali cache penuh.

Hal lain yang saya punya skrip drush yang melakukan drupal_http_request()pada semua URL saya (bukan hanya yang penting) sehingga semuanya di-cache. Cara ini dilakukan bervariasi berdasarkan situs. Kadang-kadang saya hanya bisa EFQ node yang diterbitkan, dan membangun URL seperti itu. Di lain waktu, Anda dapat meminta tabel sitemap XML untuk mendapatkan URL Anda. Saya kemudian memanggil ini dari cron sistem saya sesering yang saya butuhkan.

mpdonadio
sumber
1

Beberapa pilihan:
https://www.drupal.org/project/cache_graceful mungkin persis seperti yang Anda inginkan.

https://www.drupal.org/project/apdqc memiliki 2 kait yang menyala pada cache yang bersih memungkinkan Anda untuk mengubah yang kosong drupal_alter('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);dan setelah memungkinkan Anda bereaksi terhadap yang kosong module_invoke_all('apdqc_cache_clear', $cid, $wildcard, $this->bin, $caller);. Dapatkan APDQC bekerja dengan benar dan atur $conf['apdqc_call_hook_on_clear'] = TRUE;di file settings.php Anda & maka kait harus dipanggil setiap kali cache jelas dilakukan.

mikeytown2
sumber
1

Ini mungkin tidak cocok untuk semua orang, dan mungkin tidak cukup cepat untuk OP - karena hanya dipicu pada inisialisasi halaman berikutnya. Namun, itu membantu saya dengan memicu kode tepat setelah "cache membersihkan semua" yang tidak peka waktu.

Jelas HOOKperlu diganti dengan nama modul Anda sendiri.

/**
 * 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.
}

Jika Anda memiliki bin tertentu yang perlu Anda targetkan, yang di atas dapat dimodifikasi untuk mendukung itu, selama seluruh bin dikosongkan pada titik cache Anda kosong.

hook_inithanya dijalankan untuk halaman yang tidak di-cache. Meskipun karena cache penuh jelas berarti tidak ada halaman dalam cache, ini seharusnya tidak menyebabkan masalah. Namun, sistem caching eksternal seperti Varnish akan menghalangi pemicu ini, dan akan berarti itu hanya akan terjadi ketika permintaan yang tepat berikutnya mencapai kembali ke Drupal.

Perlu juga dicatat bahwa tergantung pada sistem caching Anda - kapan tepatnya cache_settersedia untuk semua pengguna bersamaan - bahwa pengait ini dapat dipicu beberapa kali secara bersamaan, terutama jika Anda memiliki banyak pengguna.

Pebbl
sumber
0

Saya memiliki kebutuhan yang sama, di mana klien ingin mem-flush cache Drupal dan Varnish ketika mereka menekan tombol "flush all caches". Saya membajak item menu untuk melakukannya.

Tembolok ini tidak akan mencapai cache apa pun yang dihapus pada cron atau di mana pun - hanya di tautan menu.

/**
 * 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
}
Travis Lilleberg
sumber
Thx Travis, tapi saya sedang mencari cara yang mengaitkan caching yang jelas, tidak hanya yang dipicu oleh pengguna secara bebas.
Gregory Kapustin
0

Anda mungkin ingin mencoba https://www.drupal.org/project/recacher - menggunakan modul Cache Expiration untuk mendeteksi halaman yang sudah kadaluwarsa dan kemudian melakukan cache ulang hanya halaman-halaman itu menggunakan HTTPRL yang sangat baik.

Vacilando
sumber