Bộ đệm của Laravel được lưu trữ ở đâu?

Trong thế giới phát triển web, tốc độ và hiệu suất là những điều bắt buộc phải có. Bất kể bạn đang xây dựng một trang web, phần mềm dưới dạng dịch vụ [SaaS] hay phần mềm web đặt riêng, điều quan trọng là nó phải tải nhanh để giữ cho người dùng của bạn hài lòng. Để giúp đạt được tốc độ mong muốn, chúng ta có thể sử dụng bộ nhớ đệm

Bộ nhớ đệm là phương pháp lưu trữ dữ liệu bên trong "bộ đệm" hoặc lớp lưu trữ tốc độ cao. Nó thường [nhưng không phải luôn luôn] được lưu trữ trong bộ nhớ;

Ví dụ: hãy tưởng tượng rằng chúng ta có một số truy vấn cơ sở dữ liệu cần thực hiện và mất nhiều thời gian hoặc sử dụng nhiều bộ nhớ để chạy. Để giảm chi phí này, chúng tôi có thể thực hiện truy vấn và sau đó lưu trữ kết quả của nó trong bộ đệm. Điều này có nghĩa là lần sau khi chúng ta cần chạy truy vấn này, chúng ta có thể lấy kết quả từ bộ đệm thay vì thực hiện lại truy vấn cơ sở dữ liệu

Tương tự như vậy, chúng ta cũng có thể sử dụng phương pháp này để lưu vào bộ đệm các phản hồi của các yêu cầu API bên ngoài. Ví dụ: hãy tưởng tượng rằng bạn cần đưa ra yêu cầu đối với API tỷ giá hối đoái để tìm tỷ giá hối đoái giữa hai loại tiền tệ tại một ngày và giờ nhất định. Chúng tôi có thể lưu trữ kết quả này sau khi tìm nạp một lần để chúng tôi không cần thực hiện bất kỳ yêu cầu nào trong tương lai nếu chúng tôi cần lại tỷ giá hối đoái này

Laravel cung cấp một API đơn giản nhưng mạnh mẽ để tương tác với bộ đệm. Theo mặc định, Laravel hỗ trợ bộ nhớ đệm bằng Redis, Memcached, DynamoDB, cơ sở dữ liệu, tệp và mảng

Lợi ích của việc sử dụng bộ nhớ đệm

Như đã đề cập ở trên, khi được sử dụng hiệu quả, bộ nhớ đệm có thể giảm khối lượng công việc trên hệ thống lưu trữ tệp, cơ sở dữ liệu và máy chủ ứng dụng của bạn. Ví dụ: hãy tưởng tượng rằng bạn có một truy vấn cơ sở dữ liệu phức tạp, sử dụng nhiều CPU và bộ nhớ. Nếu truy vấn này không chạy thường xuyên, nó có thể không phải là vấn đề quá lớn. Tuy nhiên, nếu truy vấn này được chạy thường xuyên, bạn có thể bắt đầu nhận thấy hiệu suất đạt được trên ứng dụng của mình. Các truy vấn sử dụng nhiều tài nguyên làm chậm truy vấn đã cho và có thể ảnh hưởng đến các phần khác trong hệ thống của bạn đối với những người dùng khác

Vì vậy, để giảm chi phí cơ sở hạ tầng do truy vấn này gây ra, chúng tôi có thể thực thi nó và sau đó lưu kết quả của nó vào bộ đệm. Bằng cách này, lần tới khi chúng tôi cần tìm nạp các kết quả này, chúng tôi sẽ có thể truy xuất chúng từ bộ đệm ẩn thay vì phải chạy lại truy vấn cơ sở dữ liệu

Chúng ta cũng có thể áp dụng logic tương tự nếu chúng ta cần chạy tập lệnh PHP đắt tiền hoặc đọc tệp thường xuyên. Bằng cách lưu vào bộ đệm đầu ra của tập lệnh hoặc nội dung của tệp, chúng tôi có thể giảm chi phí hoạt động của máy chủ ứng dụng

Tương tự như vậy, như đã đề cập ở trên, chúng tôi có thể lưu trữ các phản hồi từ các yêu cầu API bên ngoài để chúng tôi không cần thực hiện các truy vấn trùng lặp. Bằng cách thực hiện ít truy vấn hơn, chúng tôi cũng có thể giảm khả năng đạt đến giới hạn điều tiết hoặc giới hạn yêu cầu hàng tháng mà API có thể áp đặt

Như chúng ta biết, thời gian tải đang trở nên quan trọng hơn mỗi ngày, đặc biệt là khi Google đang sử dụng thời gian tải làm yếu tố xếp hạng. Nghiên cứu cho thấy rằng người dùng có xu hướng rời khỏi các trang mất hơn ba giây để tải. Hãy tưởng tượng rằng chúng ta có một truy vấn cơ sở dữ liệu mất vài giây để thực hiện. Bây giờ, một vài giây thoạt nghe có vẻ không quá tệ;

Vì vậy, do tốc độ truy xuất dữ liệu từ bộ đệm, chúng tôi có thể lưu trữ kết quả của truy vấn để không cần thực hiện lại truy vấn tốn nhiều thời gian

Lưu trữ dữ liệu trong bộ đệm

Bây giờ chúng ta đã tìm hiểu những kiến ​​thức cơ bản về bộ nhớ đệm là gì và lợi ích của việc sử dụng nó, hãy khám phá cách chúng ta có thể sử dụng nó trong các ứng dụng Laravel của mình. Với mục đích của bài viết này, chúng tôi sẽ sử dụng các truy vấn cực kỳ đơn giản, nhưng chúng vẫn nên giải thích các khái niệm tổng thể về bộ nhớ đệm trong Laravel

Giả sử rằng chúng ta có một phương thức truy vấn cơ sở dữ liệu để tìm nạp tất cả người dùng phù hợp với một tiêu chí nhất định, như trong ví dụ này

public function getUsers[$foo, $bar]
{
    return User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];
}

Nếu chúng tôi muốn cập nhật phương pháp này để nó lưu trữ kết quả của truy vấn này, chúng tôi có thể sử dụng phương pháp

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
4, phương pháp này sẽ lấy kết quả của truy vấn người dùng và sau đó lưu kết quả vào bộ đệm mà không có ngày hết hạn. Ví dụ dưới đây cho thấy cách chúng ta có thể làm điều này

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}

Bộ đệm thường là một kho lưu trữ cặp khóa-giá trị, có nghĩa là nó có một khóa duy nhất tương ứng với một giá trị [dữ liệu được lưu trong bộ nhớ đệm thực tế]. Do đó, bất cứ khi nào bạn cố gắng lưu trữ bất kỳ thứ gì trong bộ nhớ cache hoặc truy xuất nó, bạn cần đảm bảo rằng bạn đang sử dụng một khóa duy nhất để bạn không ghi đè lên bất kỳ dữ liệu đã lưu trong bộ nhớ cache nào khác

Như bạn có thể thấy trong ví dụ trên, chúng tôi đã thêm các đối số

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
5 và
public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
6 vào cuối khóa bộ đệm. Làm điều này cho phép chúng tôi tạo một khóa bộ đệm duy nhất cho từng tham số có thể được sử dụng

Cũng có thể có lúc bạn muốn lưu trữ dữ liệu của mình trong cơ sở dữ liệu nhưng lại hết hạn sử dụng. Điều này có thể hữu ích nếu bạn đang lưu trữ kết quả của một truy vấn đắt tiền được sử dụng để thống kê trên trang tổng quan hoặc báo cáo

Vì vậy, nếu chúng tôi muốn lưu trữ truy vấn của người dùng ở trên trong 10 phút, chúng tôi có thể sử dụng phương thức

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
7

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::put["user_query_results_foo_{$foo}_bar_{$bar}", $users, now[]->addMinutes[10]];

    return $users;
}

Bây giờ, sau 10 phút trôi qua, vật phẩm sẽ hết hạn và không thể truy xuất từ ​​bộ đệm [trừ khi vật phẩm đó đã được thêm lại sau đó]

Tìm nạp dữ liệu từ bộ đệm

Giả sử bạn muốn cập nhật truy vấn của người dùng từ các ví dụ trên để kiểm tra xem kết quả đã được lưu vào bộ đệm chưa. Nếu có, chúng tôi có thể tìm nạp và trả lại từ bộ đệm. Mặt khác, chúng ta có thể thực hiện truy vấn cơ sở dữ liệu, lưu kết quả vào bộ đệm trong 10 phút rồi trả lại. Để làm điều này, chúng ta có thể sử dụng đoạn mã sau

public function getUsers[$foo, $bar]
{
    $cacheKey = "user_query_results_foo_{$foo}_bar_{$bar}";

    if [Cache::has[$cacheKey]] {
        return Cache::get[$cacheKey];
    }

    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::put[$cacheKey, $users, now[]->addMinutes[10]];

    return $users;
}

Mặc dù điều này vẫn có vẻ dễ đọc, nhưng chúng ta có thể sử dụng phương thức

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
8 của Laravel để đơn giản hóa mã hơn nữa và giảm độ phức tạp của nó. Phương pháp này hoạt động giống như ví dụ của chúng tôi ở trên

public function getUsers[$foo, $bar]
{
    return Cache::remember["user_query_results_foo_{$foo}_bar_{$bar}", now[]->addMinutes[10], function [] use [$foo, $bar] {
        return User::query[]
            ->where['foo', $foo]
            ->where['bar', $bar]
            ->get[];
    }];
}

Lưu trữ dữ liệu trong suốt thời gian yêu cầu

Có thể đôi khi bạn cần chạy cùng một truy vấn nhiều lần trong cùng một yêu cầu. Như một ví dụ rất cơ bản, hãy tưởng tượng rằng bạn muốn lưu trữ truy vấn người dùng từ các ví dụ ở trên nhưng chỉ trong khoảng thời gian của yêu cầu. Bằng cách này, bạn vẫn có thể nhận được các lợi ích về tốc độ và giảm mức sử dụng tài nguyên của bộ nhớ đệm nhưng không phải lo lắng rằng dữ liệu sẽ vẫn tồn tại trong các yêu cầu khác

Để làm điều này, chúng ta có thể sử dụng trình điều khiển bộ đệm

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
9 do Laravel cung cấp. Trình điều khiển này lưu trữ dữ liệu bên trong một mảng PHP trong bộ đệm, nghĩa là khi chạy xong yêu cầu, dữ liệu được lưu trong bộ đệm sẽ bị xóa

Để chỉ ra cách chúng tôi có thể lưu trữ truy vấn người dùng ở trên trong suốt thời gian yêu cầu, chúng tôi có thể sử dụng thông tin sau

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
1

Như bạn có thể thấy trong ví dụ, chúng tôi đã sử dụng

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::put["user_query_results_foo_{$foo}_bar_{$bar}", $users, now[]->addMinutes[10]];

    return $users;
}
0 để chọn trình điều khiển bộ đệm
public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
9

Sử dụng lệnh cache của Laravel

Do cách chạy của Laravel, nó khởi động khung và phân tích cú pháp tệp tuyến đường trên mỗi yêu cầu được thực hiện. Điều này yêu cầu phải đọc tệp, phân tích cú pháp nội dung của tệp và sau đó giữ tệp theo cách mà ứng dụng của bạn có thể sử dụng và hiểu được. Vì vậy, Laravel cung cấp một lệnh tạo một tệp định tuyến duy nhất có thể được phân tích cú pháp nhanh hơn nhiều

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
4

Tuy nhiên, xin lưu ý rằng nếu bạn sử dụng lệnh này và thay đổi tuyến đường của mình, bạn sẽ cần đảm bảo chạy lệnh sau

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
5

Thao tác này sẽ xóa tệp tuyến đường đã lưu trong bộ nhớ cache để các tuyến đường mới hơn của bạn có thể được đăng ký

Tương tự như route caching, mỗi khi có yêu cầu, Laravel sẽ khởi động và mỗi tệp cấu hình trong dự án của bạn sẽ được đọc và phân tích cú pháp. Vì vậy, để ngăn việc xử lý từng tệp, bạn có thể chạy lệnh sau, lệnh này sẽ tạo một tệp cấu hình được lưu trong bộ nhớ cache

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
6

Tuy nhiên, giống như route caching ở trên, bạn cần nhớ chạy lệnh sau mỗi khi cập nhật. tệp env hoặc tệp cấu hình

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
7

Tương tự như vậy, Laravel cũng cung cấp hai lệnh khác mà bạn có thể sử dụng để lưu trữ các chế độ xem và sự kiện của mình để chúng được biên dịch trước và sẵn sàng khi có yêu cầu đối với ứng dụng Laravel của bạn. Để lưu trữ các sự kiện và chế độ xem, bạn có thể sử dụng các lệnh sau

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
0

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
1

Tuy nhiên, giống như tất cả các lệnh tạo bộ nhớ đệm khác, bạn sẽ cần nhớ phá bỏ các bộ đệm này bất cứ khi nào bạn thực hiện bất kỳ thay đổi nào đối với mã của mình bằng cách chạy các lệnh sau

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
2

public function getUsers[$foo, $bar]
{
    $users = User::query[]
        ->where['foo', $foo]
        ->where['bar', $bar]
        ->get[];

    Cache::forever["user_query_results_foo_{$foo}_bar_{$bar}", $users];

    return $user;
}
3

Những cạm bẫy phổ biến của bộ nhớ đệm

Mặc dù bộ nhớ đệm có thể mang lại những lợi ích to lớn về hiệu suất, nhưng nó cũng có thể dẫn đến một số vấn đề nếu triển khai không đúng cách.

Ví dụ: nếu dữ liệu được lưu trong bộ nhớ cache không được xử lý đúng lúc, điều đó có thể dẫn đến dữ liệu lỗi thời và cũ không chính xác. Để bối cảnh hóa điều này, hãy tưởng tượng rằng ứng dụng Laravel của chúng tôi có một số cài đặt được lưu trữ trong cơ sở dữ liệu và chúng tôi tìm nạp các cài đặt này trên mỗi lần tải trang. Vì vậy, để cải thiện tốc độ, chúng tôi quyết định lưu các cài đặt vào bộ đệm trong 10 phút. Nếu chúng tôi quên phá bộ nhớ cache trong mã của mình mỗi khi cài đặt được cập nhật, điều đó có thể dẫn đến việc cài đặt không chính xác trong tối đa 10 phút, khi đó nó sẽ tự động phá

Hơn nữa, có thể rất dễ dàng tăng độ phức tạp của cơ sở mã nếu bộ nhớ đệm được sử dụng khi không cần thiết. Như đã trình bày trong các ví dụ trên, bộ nhớ đệm rất dễ triển khai trong Laravel. Tuy nhiên, có thể lập luận rằng nếu bạn không nhận được quá nhiều hiệu suất đạt được bằng cách lưu vào bộ đệm một truy vấn hoặc phương thức cụ thể, thì bạn có thể không cần sử dụng nó. Thêm quá nhiều bộ nhớ đệm vào sai vị trí có thể dẫn đến các lỗi khó theo dõi và hành vi không thể đoán trước. Do đó, tốt hơn là chỉ thêm nó vào những nơi bạn nhận được sự cải thiện rõ ràng và rõ ràng

Ngoài ra, nếu bạn đang thêm bộ nhớ đệm vào ứng dụng Laravel của mình, điều đó thường có nghĩa là bạn cần thêm một máy chủ bộ nhớ đệm, chẳng hạn như Redis, vào cơ sở hạ tầng của ứng dụng của bạn. Sử dụng phương pháp này có thể giới thiệu một hướng tấn công bổ sung, cũng như mở thêm một cổng trên [các] máy chủ, nhưng nếu bảo mật cơ sở hạ tầng ứng dụng của bạn được định cấu hình tốt thì đó không phải là vấn đề. Tuy nhiên, nó chắc chắn phải là thứ cần ghi nhớ, đặc biệt nếu bạn đang lưu trữ thông tin nhận dạng cá nhân [PII] vào bộ đệm ẩn, vì bạn sẽ không muốn rủi ro bất kỳ dữ liệu lưu trữ nào bị rò rỉ do bị tấn công.

Phần kết luận

Hy vọng rằng bài viết này đã giải thích rõ ràng bộ nhớ đệm là gì và cách bạn có thể triển khai nó trong các ứng dụng Laravel của riêng mình để tăng hiệu suất. Như bạn có thể thấy, bộ nhớ đệm có thể được thêm vào ứng dụng của bạn thực sự dễ dàng nhờ vào API do Laravel cung cấp. Tuy nhiên, điều quan trọng là phải nhớ những cạm bẫy phổ biến nhất khi bạn thêm nó, chẳng hạn như nhớ phá bộ đệm để ngăn dữ liệu cũ hoặc lỗi thời

Chủ Đề