แนวทางปฏิบัติที่ดีที่สุดสำหรับการใช้แคชแบบกำหนดเองหรือไม่


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 () (เน้นเป็นของฉัน)

เราไม่ได้ใช้ core cache API เป็นพิเศษในการบันทึกข้อมูลที่ดึงมาเกี่ยวกับการอัพเดทที่มีอยู่ เป็นสิ่งสำคัญอย่างยิ่งที่แคชนี้จะถูกล้างเฉพาะเมื่อเราได้รับข้อมูลหลังจากทำการดึงข้อมูลการอัพเดทที่มีอยู่ใหม่ การใช้ Core Cache API ส่งผลให้เกิดปัญหาที่อาจเกิดขึ้นทุกครั้งที่พยายามดึงข้อมูลการอัพเดทที่มีอยู่ตลอดเวลารวมถึงหากไซต์มี "อายุการใช้งานแคชขั้นต่ำ" (ซึ่งเป็นขั้นต่ำและสูงสุด) หรือหากไซต์ใช้ memcache หรือระบบแคชอื่นที่เสียบได้ซึ่งถือว่าแคชที่ลบเลือนได้

โมดูลการอัพเดทจะจัดการยังคงใช้ตาราง {cache_update} แต่แทนที่จะใช้cache_set(), cache_get()และcache_clear_all()ยังมีฟังก์ชั่นผู้ช่วยส่วนตัวที่ใช้งานขั้นพื้นฐานเหล่านี้เหมือนกัน แต่มั่นใจว่าแคชไม่ได้ล้างก่อนเวลาอันควรและข้อมูลจะถูกเก็บไว้เสมอใน ฐานข้อมูลแม้ว่าจะใช้ memcache หรือแบ็กเอนด์แคชอื่นอยู่

Update Manager มีความต้องการเฉพาะที่จำเป็นเนื่องจากการพยายามดึงข้อมูลการอัปเดตบ่อยเกินไปอาจทำให้เกิดปัญหากับเซิร์ฟเวอร์ Drupal.org โดยพิจารณาว่า Update Manager สามารถดึงข้อมูลการอัปเดตจากไซต์ใด ๆ ที่ใช้ 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] ลบทุกรายการแคชที่มี ID แคชเริ่มต้นด้วยสตริงเป็นอาร์กิวเมนต์เมื่อเป็นและ ID แคชไม่ได้ ในกรณีนี้แคชจะถูกล้างด้วยรหัสต่อไปนี้[entity_type]__[entity_id]__[module_name]__[string_depending_on_where_the_cache_came_from]cache_clear_all()$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.