ข้ามไปยังเนื้อหาหลัก
คู่มือระบบ เนื้อหาผ่านการตรวจสอบแล้ว

การใช้งาน Redis Cache กับ PHP: ตัวอย่างการ Cache ข้อมูลจากฐานข้อมูล

บทความนี้สาธิตวิธีการใช้ Redis Cache กับ PHP เพื่อเพิ่มประสิทธิภาพในการดึงข้อมูลจากฐานข้อมูล MySQL โดยครอบคลุมตั้งแต่การติดตั้ง predis/predis library, การเชื่อม...

การใช้งาน Redis Cache กับ PHP: ตัวอย่างการ Cache ข้อมูลจากฐานข้อมูล

ในบทความที่แล้ว เราได้เรียนรู้วิธีการติดตั้งและตั้งค่า Redis Server บน Ubuntu ในบทความนี้ เราจะมาดูวิธีการนำ Redis Cache มาใช้งานร่วมกับ PHP เพื่อเพิ่มประสิทธิภาพในการเข้าถึงข้อมูลจากฐานข้อมูล MySQL โดยเราจะทำการ Cache ผลลัพธ์ของ query เพื่อลดภาระของ database server และเพิ่มความเร็วในการตอบสนองของแอปพลิเคชัน

ขั้นตอนที่ 1: การติดตั้ง predis/predis library

ในการใช้งาน Redis กับ PHP เราจำเป็นต้องมี library ที่ช่วยในการเชื่อมต่อและสื่อสารกับ Redis Server Library ที่นิยมใช้กันคือ predis/predis ซึ่งสามารถติดตั้งได้ง่ายๆ ผ่าน Composer:

composer require predis/predis

หลังจากรันคำสั่งนี้ Composer จะทำการดาวน์โหลดและติดตั้ง predis/predis library ลงใน project ของเรา

ขั้นตอนที่ 2: การเชื่อมต่อกับ Redis Server

เมื่อติดตั้ง library เรียบร้อยแล้ว เราสามารถเริ่มเขียนโค้ด PHP เพื่อเชื่อมต่อกับ Redis Server ได้ ตัวอย่างเช่น:

<?php

require 'vendor/autoload.php'; // โหลด Composer autoloader

try {
    $redis = new Predis\Client([
        'scheme' => 'tcp',
        'host'   => '127.0.0.1', // หรือ IP address ของ Redis server
        'port'   => 6379,        // default port
        'password' => 'your_redis_password' // หากมีการตั้ง password ใน redis.conf
    ]);

    $redis->ping(); // ตรวจสอบการเชื่อมต่อ

    echo "Connected to Redis successfully!\n";

} catch (Exception $e) {
    echo "Couldn't connect to Redis: " . $e->getMessage() . "\n";
}

?>

คำอธิบาย:

  • require 'vendor/autoload.php';: โหลด autoloader ของ Composer เพื่อให้สามารถใช้งาน predis/predis library ได้
  • new Predis\Client([...]);: สร้าง instance ของ Predis client โดยระบุ scheme (tcp), host, port และ password (ถ้ามี)
  • $redis->ping();: ส่งคำสั่ง PING ไปยัง Redis Server เพื่อตรวจสอบว่าการเชื่อมต่อสำเร็จหรือไม่
  • try...catch: ใช้เพื่อดักจับ exception ที่อาจเกิดขึ้นระหว่างการเชื่อมต่อ เช่น Redis Server ไม่พร้อมใช้งาน หรือ password ไม่ถูกต้อง

ข้อผิดพลาดที่พบบ่อย:

  • "Could not connect to Redis": ตรวจสอบให้แน่ใจว่า Redis Server กำลังทำงานอยู่ และ host, port, password ถูกต้อง
  • "php_network_getaddresses: getaddrinfo failed": ตรวจสอบว่า host name ที่ระบุสามารถ resolve ได้หรือไม่ (เช่น ในกรณีที่ใช้ domain name)

ขั้นตอนที่ 3: การ get/set ค่าใน Redis

เมื่อเชื่อมต่อกับ Redis Server ได้แล้ว เราสามารถใช้คำสั่ง get และ set เพื่ออ่านและเขียนข้อมูลใน Redis ได้ ตัวอย่างเช่น:

<?php

require 'vendor/autoload.php';

$redis = new Predis\Client([
    'scheme' => 'tcp',
    'host'   => '127.0.0.1',
    'port'   => 6379,
    'password' => 'your_redis_password'
]);

// Set ค่า
$redis->set('mykey', 'Hello Redis!');

// Get ค่า
$value = $redis->get('mykey');

echo "Value from Redis: " . $value . "\n"; // Output: Value from Redis: Hello Redis!

// Check if key exists
if ($redis->exists('mykey')) {
    echo "Key 'mykey' exists in Redis.\n";
} else {
    echo "Key 'mykey' does not exist in Redis.\n";
}

?>

คำอธิบาย:

  • $redis->set('mykey', 'Hello Redis!');: กำหนดค่า 'Hello Redis!' ให้กับ key ที่ชื่อ 'mykey'
  • $redis->get('mykey');: อ่านค่าของ key 'mykey'
  • $redis->exists('mykey');: ตรวจสอบว่า key 'mykey' มีอยู่ใน Redis หรือไม่

ขั้นตอนที่ 4: การกำหนด TTL (Time-To-Live)

TTL คือระยะเวลาที่ข้อมูลใน Redis จะถูกเก็บไว้ หลังจาก TTL หมดอายุ ข้อมูลนั้นจะถูกลบออกจาก Redis โดยอัตโนมัติ การกำหนด TTL มีประโยชน์ในการจัดการ cache data ที่มีการเปลี่ยนแปลงบ่อย ตัวอย่างเช่น:

<?php

require 'vendor/autoload.php';

$redis = new Predis\Client([
    'scheme' => 'tcp',
    'host'   => '127.0.0.1',
    'port'   => 6379,
    'password' => 'your_redis_password'
]);

// Set ค่าพร้อมกำหนด TTL เป็น 60 วินาที
$redis->setex('mykey', 60, 'This data will expire in 60 seconds.');

// Get ค่า
$value = $redis->get('mykey');

echo "Value from Redis: " . $value . "\n";

sleep(61); // Wait for 61 seconds

$value = $redis->get('mykey');

echo "Value from Redis after 61 seconds: " . $value . "\n"; // Output: Value from Redis after 61 seconds: (null)

?>

คำอธิบาย:

  • $redis->setex('mykey', 60, 'This data will expire in 60 seconds.');: กำหนดค่าพร้อม TTL โดย setex รับพารามิเตอร์ 3 ตัว: key, TTL (วินาที), และ value
  • หลังจาก 60 วินาที ข้อมูลที่เก็บไว้ใน key 'mykey' จะถูกลบออกจาก Redis ทำให้การเรียก $redis->get('mykey') คืนค่า null

ขั้นตอนที่ 5: การ cache query results

ตอนนี้เรามาดูตัวอย่างการ cache ผลลัพธ์ของ query จากฐานข้อมูล MySQL โดยสมมติว่าเรามีตาราง users ที่มี column id และ name เราต้องการ cache ข้อมูลผู้ใช้ที่มี id เท่ากับ 1

<?php

require 'vendor/autoload.php';

// Database connection parameters
$dbHost = 'localhost';
$dbName = 'mydatabase';
$dbUser = 'myuser';
$dbPass = 'mypassword';

// Redis connection parameters
$redisHost = '127.0.0.1';
$redisPort = 6379;
$redisPassword = 'your_redis_password';

try {
    // Connect to Redis
    $redis = new Predis\Client([
        'scheme' => 'tcp',
        'host'   => $redisHost,
        'port'   => $redisPort,
        'password' => $redisPassword
    ]);

    // Connect to MySQL
    $pdo = new PDO("mysql:host=$dbHost;dbname=$dbName", $dbUser, $dbPass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    $userId = 1;
    $cacheKey = 'user:' . $userId;

    // Try to get data from cache
    $cachedData = $redis->get($cacheKey);

    if ($cachedData) {
        // Data found in cache
        $user = json_decode($cachedData, true);
        echo "Data retrieved from cache:\n";
        print_r($user);
    } else {
        // Data not found in cache, fetch from database
        $stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
        $stmt->bindParam(':id', $userId);
        $stmt->execute();
        $user = $stmt->fetch(PDO::FETCH_ASSOC);

        if ($user) {
            // Store data in cache with a TTL of 300 seconds (5 minutes)
            $redis->setex($cacheKey, 300, json_encode($user));
            echo "Data retrieved from database and stored in cache:\n";
            print_r($user);
        } else {
            echo "User not found in database.\n";
        }
    }

} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}

?>

คำอธิบาย:

  • เชื่อมต่อกับทั้ง Redis Server และ MySQL database
  • กำหนด $cacheKey โดยใช้ prefix 'user:' ตามด้วย user ID เพื่อให้ง่ายต่อการจัดการ cache data
  • พยายามอ่านข้อมูลจาก cache โดยใช้ $redis->get($cacheKey)
  • ถ้าข้อมูลอยู่ใน cache ($cachedData ไม่เป็น null) ให้ decode ข้อมูลจาก JSON และแสดงผล
  • ถ้าข้อมูลไม่อยู่ใน cache ให้ query จาก database, encode ข้อมูลเป็น JSON, และเก็บไว้ใน cache ด้วย TTL 300 วินาที

กรณีใช้งานจริงและข้อผิดพลาดที่พบบ่อย:

  • Cache Miss: ในครั้งแรกที่เรียกใช้ script ข้อมูลจะยังไม่อยู่ใน cache ทำให้ต้อง query จาก database
  • Data Inconsistency: ถ้าข้อมูลใน database มีการเปลี่ยนแปลง แต่ cache ยังคงเก็บข้อมูลเก่าอยู่ จะทำให้เกิด data inconsistency แก้ไขได้โดยใช้ cache invalidation strategies ซึ่งจะกล่าวถึงในบทความถัดไป
  • Serialization: การ serialize ข้อมูลเป็น JSON ก่อนเก็บใน Redis เป็นวิธีที่ง่ายและสะดวก แต่มี overhead ในการ encode/decode หากต้องการประสิทธิภาพที่สูงขึ้น อาจพิจารณาใช้ serialization format อื่นๆ เช่น MessagePack หรือ Protocol Buffers

ในบทความนี้ เราได้เรียนรู้วิธีการใช้งาน Redis Cache ร่วมกับ PHP เพื่อเพิ่มประสิทธิภาพในการเข้าถึงข้อมูลจากฐานข้อมูล MySQL เราได้เห็นตัวอย่างการเชื่อมต่อกับ Redis Server, การ get/set ค่า, การกำหนด TTL, และการ cache query results ในบทความถัดไป เราจะมาเรียนรู้เกี่ยวกับ Cache Invalidation Strategies ซึ่งเป็นแนวทางการจัดการ cache ที่มีประสิทธิภาพ เพื่อให้มั่นใจว่าข้อมูลใน cache เป็นข้อมูลที่ถูกต้องและทันสมัยอยู่เสมอ

Office.in.th Custom Service

ต้องการพัฒนาระบบหรือปรับแต่งจากโครงสร้างนี้?

Office.in.th รับพัฒนาและออกแบบ Enterprise Web Application, API Integration และระบบบริหารงานภาครัฐ/เอกชน พร้อมการสนับสนุนระยะยาว

ดูบริการรับพัฒนาซอฟต์แวร์