เทคนิคการ cache ให้ได้ประสิทธิภาพ

ขอถามอะไรที่ไปทางวิชาการหน่อยนะครับ

อืม search เจออันนี้ ตรงกับที่ใช้งานอยู่เลย (แต่เป็น php class คนละตัว ที่ทำงานเหมือนๆกัน)
น่าจะอธิบายได้ชัดเจนขึ้น
http://www.scriptdd.com/webtip/php-cache-kit.html


<?php

#เรียก cache-kit.php
include_once('cache-kit.php');

# Config
$cache_active = true;
$cache_folder = 'cache/';

# ดึงค่าจาก Cache จาก Key ชื่อ IndexKey ในช่วง 10 วินาทีที่ผ่านมา
$result = acmeCache::fetch('IndexKey', 10); // 10 seconds

# ถ้าผ่าน 10 วินาทีไปแล้วก็ให้ดึงค่าจาก Loop ที่ควรดึงเช่น MySQL หรืออะไรต่างๆใหม่

if(!$result){

# สมมุติเป็น Loop ดึง MySQL
# วิ่งดึงค่าจาก MySQL
# ตู๊ด
# ตู๊ด

# ข้อมูลที่สมมุติว่าได้มาจาก Loop MySQL
$result = '<h2> Hello world</h2> 

Build time: '.date("F j, Y, g:i a").'</p>';

# ฝังข้อมูลลงใน Key ที่ชื่อว่า IndexKey
acmeCache::save('IndexKey', $result);

# Loop นี้ไม่ผ่าน Cache เลย แสดงข้อความออกไปซักหน่อย
echo('No Cache 
');

} else{

# ถ้าเรียกใช้ในช่วง 10 วินาทีก็จะแสดงคำว่า ข้อมูลนี้มาจากส่วนของ Cache
echo('Cached result
');

}

echo $result;

?>

ปัญหาคือ
พอ cache expire ก็จะไป query ข้อมูลใหม่
สมมติว่า query ใช้เวลา 3 วินาที ในช่วง 3 วินาทีนั้น ก็มีคนเรียกหน้าเว็บอยู่ 1000 คน
ก็จะเกิดการ query ข้อมูลใหม่ทั้ง 1000 คนที่เรียก เพราะ cache จะคืนค่า false กลับมาเนื่องจาก cache ที่สร้างไว้ expire ไปแล้ว
server ก็จะโหลดขึ้นปรี๊ดในช่วงนั้น และบางครั้งก็ก่อปัญหาให้ระบบโดยรวมไปด้วย เพราะ query ต่างๆจะช้าไปหมด

ปกติผมจะทำ file cache ครับ


&lt;?php
$_CACHE_DIR = 'cache/';
$_CACHE_TIMEOUT=30;

[quote author=siambox.com link=topic=17086.msg159876#msg159876 date=1232928197]
ปกติผมจะทำ file cache ครับ


&lt;?php
$_CACHE_DIR = 'cache/';
$_CACHE_TIMEOUT=30;

ในหนึ่ง page ผมจะมี cache มากกว่า 1

อืม… ขอบคุณนะครับ

[quote author=siambox.com link=topic=17086.msg159878#msg159878 date=1232929300]
ในหนึ่ง page ผมจะมี cache มากกว่า 1

ย้ายเข้า Articles/How-To ดีไหม ครับ

รอบ่มอีกนิด

สรุป algorithm

  1. ทำ cache ไปตามปกติ
  2. ระหว่างทำ cache ให้สร้าง lock file ขึ้นมาบอกว่าขณะนี้กำลังอยู่ระหว่างการทำ cache
  3. request ที่อยู่ระหว่างการทำ cache ให้มองหา lock file ถ้าเจอก็เรียกใช้ cache เก่า
  4. อื่นๆ ก็ใช้ cache ปัจจุบัน

lol ได้เทคนิคเพิ่มละ ^^"

ps. เทคนิคนี้ใช้กะ memcache ไม่ได้อ่า มันเล่น expire แล้วก็ลบไปเลย T_T

มา update

หลังจากแก้ไข code ใหม่เรียบร้อยเมื่อเช้า จนถึงตอนนี้ยังไม่มีอาการ load ขึ้นให้เห็น

หลังจากดูผล 1 วันได้ผลเป็นที่น่าพอใจ อาการ query ซ้อนยังมีเกิดได้อยู่แต่น้อยลงมาก
ซึ่งเป็นผลมาจากช่วงที่ลบ lock ไฟล์ออกไปแล้ว และกำลัง write cache ไฟล์ใหม่อยู่ (ซึ่งเป็นช่วงเวลาสั้นๆ)
ดังนั้น query ซ้อนที่เห็นก็จะซ้อนกันอย่างมากแค่ 2-3 process จากเดิมที่เกิดขึ้นมาเต็มไปหมด

อันนี้เป็น Code ที่ใช้งานครับ

cache.php


&lt;?php
// -------------------------------------------------------------------------//
//

พี่แมนลองแก้ให้ write cache ก่อนลบ lock file สิครับ น่าจะได้นะ

อันนี้คิดแล้วครับ แต่กลัวว่ามันจะมีปัญหา
เพราะถ้าเราไม่ลบ lock ไฟล์ออก แล้วไปเขียน cache ใหม่เลย
ระหว่างกำลังเขียนไฟล์ กลัวมันจะเกิดปัญหาว่าไฟล์ cahce อยู่ระหว่างเขียน
แล้ว process อื่นไปอ่านไฟล์นั้นมาแสดง ซึ่งอาจจะได้ผลลัพธ์ที่ผิดพลาดได้

คิดว่ามันจะ error ได้ 2 กรณีคือ

  1. ได้ข้อมูลครึ่งๆกลางๆระหว่างเขียนมาแสดง
  2. ไม่สามารถเปิดไฟล์อ่านได้ ก็จะเกิด error ที่หน้าเว็บ

หากเราลบ lock ไฟล์ออกก่อนก็จะทำให้แน่ใจได้ว่า
ระหว่างกำลังเขียน cache ไฟล์ใหม่อยู่ (ซึ่งน่าจะใช้เวลาแค่เสี้ยววินาที)
แต่ถ้ามีการเรียก process อื่นพอดีระหว่างนั้น มันก็จะไป query ซ้ำอีกรอบและสร้าง cache ใหม่อีกรอบ

จากที่เคยเจอมาจะเจอที่ กรณีที่ 2 ครับ เพราะระหว่างการเขียนจะอ่านไม่ได้อยู่แล้ว เลยทำให้ การนำ cache มาแสดงนั้นไม่สามารถทำได้ หน้า page จะ error ครับผม

แม้เซี่ยววินาทีก็มีผลครับ เพราะบางที เครื่องไปทำงานกับ disk หลายๆงาน ทำให้มันมีช่วงเวลาหลาย ms อยู่ครับ

แล้วถ้าเป็น process ที่ทำงานกับ IO นี่ ค้างแล้วไปเลยครับ

ผมว่าไม่ต่างนะ

ในระหว่างการเขียน (ยังไงก็ต้องเขียนทับไฟล์เดิม)
มันก็ต้องมีจังหวะที่เปิดไฟล์เขียนทับอยู่แล้ว ไม่ว่าจะลบ lock ก่อนหรือหลัง
แล้วถ้าแรมเหลือมันก็เขียนลงไปใน buffer ก่อน แล้วค่อยเก็บลง hdd อีกที
แล้วเขียนลงแรมคงไม่นานเป็นวิหรอกมั้งครับ lol

กำลังนั่ง debug อยู่ ว่าแบบใหนดีกว่า
เบื้องต้นเหมือนๆกัน คือมัน query ใหม่ทั้งคู่

หลังจาก debug เป็นที่เรียบร้อยได้ code ใหม่ตามนี้ครับ


&lt;?php
// -------------------------------------------------------------------------//
//

หากเป็นโปรแกรมที่เขียนเอง… ลองใช้ class ADODB ดูได้นะครับ… (ค้นคำนี้ใน google ก็จะเจอ) เป็น Class PHP ที่ช่วยในการเขียน connect กับ dbms ต่างๆได้มากมาย อีกทั้งมี cache db + session db ช่วยเสริมประสิทธิภาพงาน Inquery ได้ดีมากครับ

หลักการก็คล้ายๆที่ kke เขียนถามมาครับ และมี function call ต่างๆเป็น tool ช่วยเหลือเยอะครับ ผมไม่แน่ใจว่าเอามะพร้าว…มาขายสวนหรือเปล่านะครับ เผื่อมีใครสนใจ script ตัวนี้ก็ดีครับ