มีวิธีการขอล้างแคชหรือไม่


16

สำหรับเว็บไซต์ของสถาบันขนาดใหญ่ที่มีแคชจำนวนมากฉันต้องการสร้างแคชโดยเร็วที่สุดเพื่อไม่ให้ผู้ใช้มาถึงรุ่นแคช ...

ฉันมีชุด cron ทุกนาทีที่ทำได้โดยการใช้งานฟังก์ชั่นบางอย่างและขอหน้าสำคัญ แต่สิ่งที่ฉันกำลังมองหาคือวิธีที่จะรู้ว่าเมื่อแคชเพิ่งจะถูกล้างโดยเฉพาะอย่างยิ่งตะขอดังนั้นฉันสามารถเปิดสิ่งนี้ สร้างฟังก์ชั่น

ความคิดใด ๆ


ขึ้นอยู่กับสิ่งที่คุณพยายามทำให้สำเร็จคำตอบของ Phayes ในหน้านี้เป็นทางออกที่ดีในการปลดรหัสหลังจากแคชถูกล้างออก
Lester Peabody

คำตอบ:


7

ไม่มีใน Drupal 7.x แต่ถูกเพิ่มเป็นตะขอหลัก, hook_rebuildใน Drupal 8.x หลังจากมีคนร้องขอมากพอ อาจมีวิธีที่ดีกว่าในการแก้ปัญหาของคุณใน 7.x - คุณกำลังพยายามเริ่มต้นการทำงานของการร้อนแคชบางชนิดหลังจาก cron ล้างแคชถูกต้องหรือไม่ อีกวิธีในการเข้าถึงสิ่งนี้คือการใช้Elysia cronซึ่งมีการปรับปรุงที่สำคัญหลายประการเกี่ยวกับวิธีการทำงานของ cron แต่สองวิธีที่อาจเกี่ยวข้องกับกรณีการใช้งานของคุณคือ:

Elysia Cron ขยาย cron มาตรฐานของ Drupal ทำให้สามารถควบคุมธัญพืชได้ดีในแต่ละงานและหลายวิธีในการเพิ่มงาน cron ที่กำหนดเองในเว็บไซต์ของคุณ

  • ตั้งค่าเวลาและความถี่ของแต่ละงาน cron (คุณสามารถเรียกใช้งานบางอย่างทุกวันในเวลาที่กำหนดอื่น ๆ เท่านั้นรายเดือนและอื่น ๆ ... ) สำหรับแต่ละงานคุณสามารถเลือกระหว่างตัวเลือกที่ใช้บ่อย ๆ ("วันละครั้ง", "เดือนละครั้ง" ... ) หรือใช้ซินแทกซ์ที่เหมือน "linux crontab" ที่ทรงพลังเพื่อตั้งค่าเวลาที่ถูกต้อง คุณสามารถกำหนดตัวเลือกที่ใช้บ่อยเพื่อเพิ่มความรวดเร็วในการกำหนดค่าไซต์ ...
  • เปลี่ยนลำดับความสำคัญ / ลำดับของการดำเนินงาน ...

คุณสามารถใช้โมดูลนี้เพื่อควบคุมการทำงานของ cron ให้ดีขึ้นเพื่อช่วยแก้ไขปัญหาแคชเก่า โดยเฉพาะคุณสามารถเพิ่มตะขอลงในฟังก์ชั่นการสร้างใหม่ของคุณไปที่ cron แล้วใช้ Elysia cron ตั้งค่าการดำเนินการเหล่านี้ให้ทำงานทันทีหลังจากการดำเนินการล้างแคช

นอกจากนี้ดูเหมือนว่าคุณอาจมีปัญหากับ cron ที่ใช้งานบ่อยนำไปสู่การสร้างแคชบ่อยเกินไป หากเป็นเช่นนั้นคุณสามารถตั้งค่าการดำเนินการล้างแคชเฉพาะใน Elysia cron ให้ทำงานในอัตราที่แตกต่างจากการดำเนินการ cron ที่เหลือของคุณดังนั้นตัวอย่างเช่นการทำดัชนีการค้นหาจะอัปเดตทุก 5 นาที แต่การล้างแคชทั้งหมดจะทำงานทุก ๆ 6 ชั่วโมงเป็นต้น

ปรับแต่งการจัดการแคช cron: drupal cron จะทำให้แคชตัวแปรไม่ถูกต้องทุกครั้งที่ cron ทำงานและนี่เป็นปัญหาด้านประสิทธิภาพที่ยอดเยี่ยมหากคุณมีงานที่เรียกบ่อย Elysia cron เพิ่มประสิทธิภาพการจัดการแคชและไม่จำเป็นต้องทำให้แคชใช้ไม่ได้


นี่คือคนเกียจคร้านจริง รีบ D8! อันที่จริงฉันมีชีวิตอยู่ตามที่ฉันบอกคุณ cron กับ elysia_cron วิ่งทุกนาทีทำให้อุ่นสิ่งที่ฉันต้องการ แต่เนื่องจากเว็บไซต์ของฉันจะมี> 10.000 / การเข้าชม / ชั่วโมงฉันค่อนข้างแน่ใจว่า sbdy จะตกอยู่ในแคชที่ว่างเปล่า ... ขอบคุณดังนั้นฉันรู้แล้วว่าตอนนี้มันมีข้อ จำกัด D7!
Gregory Kapustin

12

วิธีการทำเช่นนี้คือการใช้ร่วมกับ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วิธีที่ไม่เคยตั้งใจจะใช้ แต่ก็ควรทำในสิ่งที่คุณต้องการ


ฉันชอบวิธีนี้มาก ก่อนที่จะใช้มันเองฉันค้นหาสำหรับการใด ๆ ที่รู้จักกัน / ปัญหาความขัดแย้งที่ใช้register_shutdown_function()ใน Drupal, และมาข้าม Drupal หลักของdrupal_register_shutdown_function () : "Wrapper สำหรับ register_shutdown_function () ที่จับโยนข้อยกเว้นที่จะหลีกเลี่ยง 'ข้อยกเว้นโยนไม่รวมกรอบสแต็คในที่ไม่รู้จัก' . ฉัน รู้ว่ามันทำให้ฉันรู้สึกดีขึ้นabusing hook_flush_cachesถ้าฉันใช้เฉพาะฟังก์ชั่นหลักของ Drupal เท่านั้น
runswithscissors

11

ไม่ไม่มี ไม่ได้จริงๆ อย่างน้อยไม่ใช่ใน 6 หรือ 7 สมมติว่า 7:

ถ้าคุณจะมองไปที่คุณจะเห็นมันจะเรียกdrupal_flush_all_caches() hook_flush_caches()เบ็ดนี้มีวัตถุประสงค์เพื่อ:

"เพิ่มชื่อตารางแคชลงในรายการตารางแคชที่จะถูกล้างโดยปุ่มล้างบนหน้าประสิทธิภาพหรือทุกครั้งที่มีการเรียกใช้ drupal_flush_all_caches"

มันจะเป็นการดึงดูดให้โมดูลของ hook ของคุณใช้งานได้นานและเขียนโค้ดที่นั่น 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_boot, hook_exit, hook_watchdogและhook_language_init- ตะขอคุณไม่ต้องการที่จะใช้เพียงเพื่อให้การทำงานแคชชัดเจนขึ้นอยู่กับ


Dammit ใช้เวลานานพอสมควรในการเพิ่มลิงก์เหล่านี้ทั้งหมด) จะทิ้งมันไว้ตอนนี้เพราะฉันไม่สามารถบังคับตัวเองให้ลบมันได้หลังจากใช้เวลานานมากในการอธิบายว่าทำไมมันไม่สามารถทำได้
Mołot

3
ทิ้งไว้มันเป็นคำตอบที่ดี
mpdonadio

ใช่ปล่อยให้มันฉันไม่สามารถตรวจสอบคำตอบที่ดี แต่ฉันนิดหนึ่งมัน :)
เกรกอรี่ Kapustin

8

จังหวะกว้างที่นี่:

ในขณะที่ไม่มีตะขออยู่ใน pre-D8 คุณสามารถเขียนแบ็กเอนด์ฐานข้อมูลของคุณตามมาตรฐานDrupalDatabaseCacheและจากนั้นเขียนตรรกะใด ๆ หรือทั้งหมดลงในclear()ฟังก์ชั่นของคุณ การดูอย่างรวดเร็วจะแนะนำสิ่งนี้ให้ตรงไปตรงมาอย่างสมเหตุสมผลใน D7 (เพียงคัดลอกคลาสไปยังชื่อที่กำหนดเองของคุณและแก้ไขมัน ฯลฯ โดยการขว้างmodule_invoke_all()ตามความเหมาะสม) และด้วยโมดูล cache_backportจะทำงานได้ใน D6 จากนั้นชี้ช่องเก็บแคชใด ๆ ที่คุณต้องการให้เป็นแบบใสและคุณควรจะไป


3
นี่อาจเป็นทางออกที่ดีที่สุดเพียง 'ปัญหา' ซึ่งหากคุณมีถังขยะหลายถัง (memcache, Redis และอื่น ๆ ) คุณจะต้องขยายแคชหลายชั้น ยังคงคุ้มค่าแม้ว่า
Clive

จะไม่ทำงานกับแคชใน memcached, apc หรือโซลูชันอื่นที่ไม่ใช่ db ได้หรือไม่
Mołot

ฉันใช้ Redis ไม่แน่ใจว่าจะได้ผล
เกรกอรี่ Kapustin

หากคุณกำลังใช้drupal.org/project/redisคุณควรจะสามารถคัดลอกหรือแก้ไขคลาสอื่น ๆ ที่ให้มาในโมดูลที่กำหนดเองแล้วใช้แทน อย่างไรก็ตามหากคุณกำลังใช้บางสิ่งบางอย่างตามแนวของแพลตฟอร์มแพนธีออนที่ซึ่งพวกเขาให้การยกที่หนักหน่วงสำหรับ Redis แล้วใช่คุณจะต้องประสานงานกับพวกเขาเกี่ยวกับสิ่งนี้ทั้งหมด
Jimajamma

3

หากคุณมองไปที่แหล่งที่มาของdrupal_flush_all_caches()และclear_cache_all()คุณจะเห็นว่าไม่มีการเรียกใช้ hooks การยกเลิกการโพสต์ซึ่งเป็นคนเกียจคร้านที่น่ารำคาญ

เป็นการยากมากที่จะรับประกันว่าผู้ใช้จะไม่ต้องรอให้สร้างรายการแคชบางรายการดังนั้นฉันจึงพยายามหลีกเลี่ยงการล้างแคชแบบเต็มให้มากที่สุด

วิธีการหนึ่งที่ช่วยได้จริงๆคือสร้างหน้าผลการดำเนินงานเพื่อต่อเชื่อมตัวจัดการการส่งที่จะล้างแคชที่หันไปข้างหน้าและไม่ได้สัมผัสเมนูรีจิสทรีและแคชหลักที่คล้ายกัน ฉันมีผลลัพธ์ที่ดีด้วยสิ่งนี้เนื่องจากเมนูและการสร้างรีจิสทรีใช้เวลาประมาณครึ่งหนึ่งในการสร้างแคชใหม่

อีกสิ่งหนึ่งที่ฉันมีสคริปต์ที่น่าเบื่อที่ทำdrupal_http_request()กับ 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 ของคุณจากนั้นจึงเรียกใช้ hooks ทุกครั้งที่ล้างแคช


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 และวานิชเมื่อพวกเขากดปุ่ม "ล้างแคชทั้งหมด" ฉันถูกแย่งชิงรายการเมนูที่จะทำ

การทำเช่นนี้จะไม่ทำให้เกิดการลบแคชใด ๆ บน 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
}

ขอบคุณ Travis แต่ฉันกำลังมองหาวิธีที่เกี่ยวกับการแคชที่ชัดเจนไม่เพียง แต่ผู้ใช้ทริกเกอร์โดยสมัครใจ
Gregory Kapustin

0

คุณอาจต้องการลองhttps://www.drupal.org/project/recacher - โดยใช้โมดูลการหมดอายุของแคชเพื่อตรวจหาหน้าที่หมดอายุแล้วจึงทำการแคชเฉพาะหน้าเหล่านั้นโดยใช้ HTTPRL ที่ยอดเยี่ยม

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.