Bạn đã bao giờ tự hỏi tại sao một số trang web tải gần như ngay lập tức, trong khi những trang khác lại khiến bạn phải chờ đợi mệt mỏi? Câu trả lời thường nằm ở một công nghệ gọi là “cache”. Cache, hay bộ nhớ đệm, hoạt động như một bộ nhớ tạm thời, lưu trữ các phiên bản của trang web để phục vụ người dùng nhanh hơn trong những lần truy cập sau. Vai trò của nó trong việc tối ưu hiệu suất web là cực kỳ quan trọng. Khi một trang web không sử dụng cache, mỗi yêu cầu từ người dùng đều buộc máy chủ phải xử lý lại từ đầu, gây ra tình trạng tải chậm và tăng vọt tải CPU, đặc biệt khi có nhiều người truy cập cùng lúc.
Trong bối cảnh đó, Nginx là gì nổi lên như một giải pháp mạnh mẽ và hiệu quả. Không chỉ là một máy chủ web hiệu suất cao, Nginx còn cung cấp các cơ chế cache cực kỳ linh hoạt và dễ cấu hình. Việc tận dụng tính năng này giúp giảm đáng kể thời gian phản hồi, tiết kiệm tài nguyên máy chủ và cải thiện trải tr nghiệm người dùng một cách rõ rệt. Bài viết này sẽ hướng dẫn bạn từ những khái niệm cơ bản nhất về Nginx cache cho đến các bước cấu hình chi tiết và mẹo tối ưu chuyên sâu, giúp bạn làm chủ công cụ mạnh mẽ này.

Tổng quan về Nginx và chức năng cache
Giới thiệu về máy chủ Nginx
Nginx (phát âm là “engine-x”) là một máy chủ web là gì mã nguồn mở hiệu suất cao. Ban đầu được tạo ra để giải quyết vấn đề C10k (xử lý mười nghìn kết nối đồng thời), Nginx đã nhanh chóng trở nên phổ biến nhờ kiến trúc hướng sự kiện, không đồng bộ, giúp nó sử dụng tài nguyên hệ thống một cách cực kỳ hiệu quả. Ưu điểm vượt trội của Nginx là khả năng xử lý hàng ngàn kết nối cùng lúc với mức tiêu thụ bộ nhớ rất thấp, lý tưởng cho các hệ thống có lưu lượng truy cập cao.
Ngoài vai trò là một máy chủ web, Nginx còn được sử dụng rộng rãi như một reverse proxy, load balancer (bộ cân bằng tải), và HTTP cache. Trong các hệ thống web hiện đại, Nginx thường được đặt ở phía trước các server là gì ứng dụng (như Apache, Node.js, hoặc PHP-FPM) để xử lý các yêu cầu đến, phân phối tải, và phục vụ các nội dung tĩnh một cách nhanh chóng. Chính khả năng đa năng và hiệu suất vượt trội này đã giúp Nginx trở thành một trong những máy chủ web phổ biến nhất thế giới, được tin dùng bởi các gã khổng lồ công nghệ như Netflix, Airbnb và Cloudflare.
Chức năng cache trong Nginx
Một trong những tính năng mạnh mẽ nhất của Nginx chính là khả năng lưu trữ bộ nhớ đệm (cache). Chức năng này cho phép Nginx lưu lại các phản hồi từ máy chủ backend (máy chủ ứng dụng) và sử dụng lại chúng để trả lời cho các yêu cầu tương tự trong tương lai. Điều này giúp giảm đáng kể số lượng yêu cầu cần được xử lý bởi backend, từ đó giảm tải cho máy chủ và tăng tốc độ phản hồi cho người dùng cuối.
Nginx hỗ trợ nhiều loại cache khác nhau, trong đó phổ biến nhất là:
- proxy_cache: Dùng khi Nginx hoạt động như một reverse proxy. Nó lưu lại các phản hồi từ máy chủ backend (ví dụ: Node.js, Python, Java). Đây là giải pháp cache linh hoạt cho hầu hết các loại ứng dụng web.
- fastcgi_cache: Được thiết kế đặc biệt để cache các phản hồi từ ứng dụng FastCGI, điển hình là các ứng dụng PHP chạy với PHP-FPM. Đây là lựa chọn tối ưu cho các website WordPress, Laravel và các mã nguồn PHP khác.
- microcache: Một kỹ thuật nâng cao, thường được thực hiện bằng cách thiết lập thời gian hết hạn cache rất ngắn (ví dụ 1 giây). Nó cực kỳ hiệu quả trong việc xử lý các đợt tăng đột biến lưu lượng truy cập mà vẫn đảm bảo nội dung gần như là thời gian thực.
Vai trò của cache trong Nginx là không thể thiếu để xây dựng một hệ thống web hiệu suất cao, giúp trang web của bạn nhanh hơn, chịu tải tốt hơn và tiết kiệm chi phí vận hành.

Hướng dẫn cấu hình proxy cache trong Nginx
Định nghĩa và nguyên lý hoạt động của proxy cache
Proxy cache là cơ chế mà Nginx, khi đóng vai trò là một reverse proxy, sẽ lưu trữ một bản sao của nội dung được phản hồi từ các máy chủ backend (máy chủ ứng dụng thực sự). Khi một người dùng gửi yêu cầu đến Nginx, thay vì chuyển tiếp yêu cầu đó đến backend ngay lập tức, Nginx sẽ kiểm tra xem nó có bản sao hợp lệ của nội dung được yêu cầu trong bộ nhớ đệm của mình hay không.
Nguyên lý hoạt động khá đơn giản:
- Lần yêu cầu đầu tiên (Cache MISS): Người dùng yêu cầu một trang. Nginx kiểm tra cache nhưng không tìm thấy nội dung. Nginx chuyển tiếp yêu cầu đến máy chủ backend. Backend xử lý và trả về phản hồi. Trước khi gửi phản hồi cho người dùng, Nginx lưu một bản sao của nó vào cache.
- Những lần yêu cầu tiếp theo (Cache HIT): Một người dùng khác (hoặc cùng một người dùng) yêu cầu lại trang đó. Nginx kiểm tra cache và tìm thấy một bản sao hợp lệ. Nginx sẽ trả về nội dung trực tiếp từ cache mà không cần làm phiền đến máy chủ backend.
Quá trình này giúp giảm đáng kể độ trễ và giảm tải cho backend, cho phép nó tập trung vào việc xử lý các yêu cầu động hoặc các tác vụ phức tạp khác.
Các bước thiết lập proxy_cache trong Nginx
Thiết lập proxy cache trong Nginx bao gồm việc định nghĩa một “vùng” lưu trữ cache và sau đó áp dụng nó vào các location (đường dẫn) mà bạn muốn cache.
Bước 1: Cấu hình zone cache với proxy_cache_path
Chỉ thị này được đặt trong khối http của file cấu hình nginx.conf. Nó định nghĩa vị trí và các tham số cho bộ nhớ đệm.
http {
# ... các cấu hình khác ...
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off;
# ...
}
Hãy cùng phân tích các tham số:
/var/cache/nginx: Đường dẫn đến thư mục lưu trữ các file cache. Đảm bảo Nginx có quyền ghi vào thư mục này.levels=1:2: Tạo cấu trúc thư mục phân cấp để lưu file cache, giúp truy xuất nhanh hơn.1:2có nghĩa là tạo một thư mục con có tên 1 ký tự và thư mục con cấp hai có tên 2 ký tự.keys_zone=my_cache:10m: Tạo một vùng nhớ chia sẻ tên làmy_cachevới dung lượng10m(10 megabytes) để lưu trữ các key của cache. Dung lượng này không phải là dung lượng cache, mà chỉ là nơi lưu trữ “mục lục” của cache. 1MB có thể lưu khoảng 8000 key.max_size=10g: Thiết lập dung lượng tối đa cho cache trên đĩa là10g(10 gigabytes).inactive=60m: Các file cache không được truy cập trong vòng60m(60 phút) sẽ bị xóa, bất kể chúng còn hợp lệ hay không.use_temp_path=off: Hướng dẫn Nginx ghi file trực tiếp vào thư mục cache thay vì ghi vào một thư mục tạm thời trước. Điều này giúp tránh các thao tác sao chép file không cần thiết.

Bước 2: Áp dụng cache và thiết lập proxy_cache_key
Bây giờ, trong khối server hoặc location của bạn, hãy kích hoạt cache và định nghĩa cách Nginx tạo key cho mỗi đối tượng cache.
server {
# ...
location / {
proxy_pass http://my_backend_server;
# Kích hoạt cache bằng cách tham chiếu đến zone đã tạo
proxy_cache my_cache;
# Định nghĩa key để lưu cache, thường dựa trên scheme, host và URI
proxy_cache_key "$scheme$request_method$host$request_uri";
# Thiết lập thời gian cache cho các mã phản hồi khác nhau
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
# Thêm header để kiểm tra trạng thái cache (HIT, MISS, BYPASS, ...)
add_header X-Cache-Status $upstream_cache_status;
}
# ...
}
Trong ví dụ trên:
proxy_cache my_cache;nói với Nginx sử dụng vùng cache có tênmy_cachemà chúng ta đã định nghĩa trước đó.proxy_cache_keyxác định chuỗi duy nhất cho mỗi yêu cầu. Cấu hình mặc định thường đã đủ tốt cho hầu hết các trường hợp.proxy_cache_validchỉ định thời gian lưu cache cho các mã phản hồi HTTP. Ở đây, các phản hồi200(Thành công) và302(Chuyển hướng tạm thời) được cache trong 10 phút, còn lỗi404(Không tìm thấy) chỉ được cache 1 phút.add_header X-Cache-Statuslà một cách rất hữu ích để gỡ lỗi, cho phép bạn xem trạng thái của cache ngay trong trình duyệt.
Sau khi thêm các cấu hình này, hãy kiểm tra cú pháp (nginx -t) và tải lại Nginx (systemctl reload nginx) để áp dụng thay đổi.
Cài đặt và cấu hình fastcgi cache để tăng tốc độ tải trang
Tìm hiểu fastcgi_cache và ưu điểm
Trong khi proxy_cache là giải pháp tuyệt vời cho việc cache phản hồi từ bất kỳ máy chủ HTTP nào, fastcgi_cache lại là một công cụ được tối ưu hóa đặc biệt cho các ứng dụng web sử dụng giao thức FastCGI. Đây là trường hợp cực kỳ phổ biến với các trang web xây dựng trên nền tảng PHP, chẳng hạn như WordPress, Joomla, Drupal, hoặc các framework như Laravel và Symfony, nơi Nginx giao tiếp với PHP thông qua PHP-FPM (FastCGI Process Manager).
Bạn nên sử dụng fastcgi_cache khi trang web của bạn chủ yếu được cung cấp bởi PHP. Ưu điểm chính của nó là khả năng cache trực tiếp kết quả đầu ra của quá trình thực thi PHP. Thay vì phải thực thi lại toàn bộ code PHP và truy vấn cơ sở dữ liệu cho mỗi lượt truy cập, Nginx có thể trả về trang HTML đã được tạo sẵn từ cache. Điều này mang lại lợi ích to lớn:
- Tăng tốc độ tải trang: Thời gian phản hồi giảm từ vài trăm mili giây (hoặc thậm chí vài giây) xuống chỉ còn vài mili giây.
- Giảm tải máy chủ: CPU và bộ nhớ của máy chủ được giải phóng vì không cần phải chạy các tiến trình PHP nặng nề.
- Tăng khả năng chịu tải: Website có thể phục vụ số lượng người dùng đồng thời lớn hơn nhiều lần mà không bị quá tải.
Đối với các website WordPress, fastcgi_cache là một giải pháp thay thế hiệu quả cho các plugin cache phổ biến, vì nó hoạt động ở cấp độ máy chủ, thường nhanh hơn và hiệu quả hơn so với việc cache ở cấp độ ứng dụng PHP.

Hướng dẫn chi tiết cấu hình fastcgi_cache
Việc cấu hình fastcgi_cache có nhiều điểm tương đồng với proxy_cache, chỉ khác ở tên các chỉ thị.
Bước 1: Định nghĩa cache zone trong khối http
Tương tự như proxy_cache_path, bạn cần dùng fastcgi_cache_path trong file nginx.conf.
http {
# ...
fastcgi_cache_path /var/cache/nginx_fcgi levels=1:2 keys_zone=php_cache:100m max_size=10g inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
# ...
}
Ở đây, keys_zone=php_cache:100m tạo một vùng nhớ tên là php_cache với dung lượng 100MB để lưu trữ các key. Các tham số khác có ý nghĩa tương tự như proxy_cache_path.
Bước 2: Áp dụng cache vào location xử lý PHP
Trong khối server của bạn, hãy tìm đến location xử lý các file .php và thêm các chỉ thị fastcgi_cache.
Đây là một ví dụ kịch bản cấu hình fastcgi_cache cho một trang WordPress:
server {
# ...
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
# Kích hoạt FastCGI cache
fastcgi_cache php_cache;
# Thiết lập thời gian cache mặc định
fastcgi_cache_valid 200 60m;
# Chỉ cache các yêu cầu GET và HEAD
fastcgi_cache_methods GET HEAD;
# Bỏ qua cache cho một số điều kiện
# Không cache nếu có cookie wordpress_logged_in
if ($http_cookie ~* "wordpress_logged_in_") {
set $skip_cache 1;
}
# Không cache các trang admin, cron, ajax
if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|/feed/|index.php|sitemap(_index)?.xml") {
set $skip_cache 1;
}
# Không cache nếu có tham số truy vấn (trừ một vài trường hợp an toàn)
if ($query_string != "") {
set $skip_cache 1;
}
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
# Thêm header để kiểm tra
add_header X-FastCGI-Cache $upstream_cache_status;
}
# ...
}
Trong cấu hình này:
fastcgi_cache php_cache;kích hoạt vùng cachephp_cache.fastcgi_cache_valid 200 60m;thiết lập cache hợp lệ trong 60 phút cho các phản hồi thành công.- Phần quan trọng là logic bỏ qua cache. Chúng ta sử dụng biến
$skip_cacheđể không lưu cache cho người dùng đã đăng nhập (dựa trên cookiewordpress_logged_in_), không cache các trang quản trị, và các trang có tham số truy vấn (thường là các trang tìm kiếm, lọc sản phẩm…). fastcgi_cache_bypass $skip_cache;vàfastcgi_no_cache $skip_cache;sử dụng biến$skip_cacheđể quyết định khi nào cần bỏ qua cache.add_header X-FastCGI-Cachegiúp bạn dễ dàng xác nhận xem cache có đang hoạt động hay không.
Sau khi lưu cấu hình, hãy nhớ kiểm tra và tải lại Nginx để các thay đổi có hiệu lực.
Quản lý thời gian lưu cache và cập nhật cache hiệu quả
Cách thiết lập thời gian hết hạn cache (cache expiry)
Thiết lập thời gian hết hạn cache (còn gọi là TTL – Time To Live) là một trong những yếu tố quan trọng nhất để cân bằng giữa hiệu suất và tính cập nhật của nội dung. Nếu thời gian quá ngắn, bạn sẽ không tận dụng được tối đa lợi ích của cache. Ngược lại, nếu thời gian quá dài, người dùng có thể nhìn thấy nội dung cũ đã lỗi thời.
Nginx cung cấp các chỉ thị rất linh hoạt để kiểm soát việc này.
Đối với proxy_cache:
Sử dụng chỉ thị proxy_cache_valid. Bạn có thể thiết lập thời gian khác nhau cho các mã trạng thái HTTP khác nhau.
location / {
proxy_pass http://my_backend_server;
proxy_cache my_cache;
# Cache các phản hồi thành công (200) và chuyển hướng vĩnh viễn (301) trong 24 giờ.
proxy_cache_valid 200 301 24h;
# Cache các phản hồi chuyển hướng tạm thời (302) trong 10 phút.
proxy_cache_valid 302 10m;
# Cache các lỗi như "Not Found" (404) trong 1 phút để giảm tải khi bị tấn công.
proxy_cache_valid 404 1m;
# Thiết lập thời gian cache mặc định cho tất cả các mã trạng thái khác.
proxy_cache_valid any 5m;
}
Cú pháp proxy_cache_valid [mã trạng thái ...] [thời gian]; cho phép bạn tùy chỉnh rất chi tiết. Ví dụ, bạn có thể cache nội dung tĩnh (hình ảnh, CSS) trong thời gian dài (vài ngày hoặc vài tuần) và cache các trang HTML trong thời gian ngắn hơn (vài phút hoặc vài giờ).
Đối với fastcgi_cache:
Tương tự, chỉ thị fastcgi_cache_valid được sử dụng với cú pháp giống hệt.
location ~ \.php$ {
# ...
fastcgi_cache php_cache;
# Cache các trang PHP thành công trong 60 phút.
fastcgi_cache_valid 200 60m;
# Cache các trang lỗi trong 5 phút.
fastcgi_cache_valid 403 404 5m;
}
Việc lựa chọn thời gian hợp lý phụ thuộc vào tần suất cập nhật nội dung của bạn. Một trang tin tức có thể cần thời gian cache ngắn, trong khi một trang giới thiệu công ty có thể cache trong thời gian dài.

Phương pháp làm mới cache và xóa cache (cache purge)
Ngay cả với thời gian hết hạn được cấu hình cẩn thận, sẽ có những lúc bạn cần xóa một trang cụ thể ra khỏi cache ngay lập tức. Ví dụ, khi bạn vừa cập nhật một bài viết quan trọng hoặc sửa một lỗi sản phẩm, bạn không thể đợi cho đến khi cache tự hết hạn. Đây là lúc kỹ thuật xóa cache (cache purge) phát huy tác dụng.
Nginx mặc định không có cơ chế xóa cache trực tiếp, nhưng có nhiều cách để thực hiện điều này:
1. Sử dụng proxy_cache_bypass (Cách đơn giản):
Bạn có thể cấu hình Nginx để bỏ qua việc đọc từ cache (nhưng vẫn có thể ghi vào cache) nếu một điều kiện nào đó được đáp ứng, ví dụ như một header hoặc cookie đặc biệt.
http {
# ...
# map $http_secret_header $bypass_cache {
# default 0;
# "mysecret" 1;
# }
}
server {
location / {
proxy_pass http://my_backend_server;
proxy_cache my_cache;
proxy_cache_bypass $bypass_cache;
# ...
}
}
Với cấu hình này, nếu bạn gửi một yêu cầu với header Secret-Header: mysecret, Nginx sẽ bỏ qua cache và lấy nội dung mới nhất từ backend.
2. Sử dụng module ngx_cache_purge (Cách mạnh mẽ):
Đây là một module của bên thứ ba (hoặc được tích hợp sẵn trong một số bản phân phối Nginx) cho phép bạn gửi một yêu cầu đặc biệt để xóa một đối tượng cụ thể khỏi cache.
location ~ /purge(/.*) {
# Giới hạn IP được phép xóa cache
allow 127.0.0.1;
deny all;
proxy_cache_purge my_cache "$scheme$request_method$host$1";
}
Với cấu hình trên, để xóa cache của trang /my-article, bạn chỉ cần truy cập vào URL /purge/my-article từ một IP được cho phép. Nhiều plugin cache WordPress như “Nginx Helper” sử dụng cơ chế này để tự động xóa cache khi bạn cập nhật bài viết.
3. Xóa thủ công:
Trong trường hợp khẩn cấp, bạn luôn có thể xóa toàn bộ thư mục cache trên máy chủ bằng lệnh rm -rf /var/cache/nginx/*. Tuy nhiên, cách này sẽ xóa toàn bộ cache, làm tăng đột ngột tải lên máy chủ backend khi cache cần được tạo lại từ đầu. Do đó, hãy sử dụng một cách thận trọng.
Các bước kiểm tra và đánh giá tính hiệu quả của cache trên Nginx
Kiểm tra cache hits và cache misses
Sau khi cấu hình, làm thế nào để bạn biết cache có thực sự hoạt động và mang lại hiệu quả? Cách đơn giản và trực tiếp nhất là kiểm tra trạng thái cache cho mỗi yêu cầu. Nginx cung cấp một biến nội bộ là $upstream_cache_status để thực hiện việc này.
Để hiển thị trạng thái này, bạn chỉ cần thêm một header vào phản hồi của Nginx. Chúng ta đã làm điều này trong các ví dụ cấu hình ở trên:
add_header X-Cache-Status $upstream_cache_status;
Hoặc đối với FastCGI:
add_header X-FastCGI-Cache $upstream_cache_status;
Bây giờ, bạn có thể sử dụng các công cụ như curl hoặc Developer Tools của trình duyệt để kiểm tra header này.
curl -I https://yourdomain.com/some-page
Bạn sẽ thấy một dòng trong kết quả, ví dụ X-Cache-Status: MISS.
Các giá trị phổ biến của $upstream_cache_status bao gồm:
- MISS: Yêu cầu không được tìm thấy trong cache. Nginx đã chuyển nó đến backend và có thể sẽ lưu phản hồi vào cache. Đây là trạng thái bạn sẽ thấy ở lần truy cập đầu tiên.
- HIT: Yêu cầu đã được phục vụ trực tiếp từ cache. Đây là điều chúng ta mong muốn! Nó cho thấy backend không phải làm việc và phản hồi được trả về cực nhanh.
- EXPIRED: Mục trong cache đã hết hạn. Nginx sẽ chuyển yêu cầu đến backend để lấy nội dung mới.
- BYPASS: Nginx đã được chỉ thị bỏ qua cache cho yêu cầu này (ví dụ, do cấu hình
proxy_cache_bypass). - STALE: Nginx đã phục vụ một mục cache cũ (hết hạn) vì không thể lấy được nội dung mới từ backend (ví dụ, backend bị lỗi).
Bằng cách theo dõi các trạng thái này, đặc biệt là tỷ lệ giữa HIT và MISS, bạn có thể đánh giá được mức độ hiệu quả của chiến lược cache của mình. Một tỷ lệ HIT cao cho thấy bạn đang tiết kiệm được rất nhiều tài nguyên.

Đánh giá cải thiện hiệu suất và tải server
Kiểm tra header chỉ cho bạn biết cache có hoạt động hay không. Để thấy được tác động thực sự, bạn cần đo lường sự cải thiện về hiệu suất.
1. So sánh tốc độ phản hồi:
Sử dụng các công cụ đo tốc độ web như Google PageSpeed Insights, GTmetrix, hoặc thậm chí là công cụ dòng lệnh như time curl.
- Trước khi có cache: Chạy lệnh
time curl -o /dev/null https://yourdomain.comnhiều lần và ghi lại thời gian phản hồi. - Sau khi có cache: Tải lại trang một lần để cache được tạo (bạn sẽ thấy
MISS). Sau đó, chạy lại lệnhtime curlnhiều lần. Bạn sẽ thấy thời gian phản hồi (giá trịreal) giảm đi đáng kể, thường là từ hàng trăm mili giây xuống chỉ còn vài chục mili giây.
Sự khác biệt về thời gian phản hồi của máy chủ (Time to First Byte – TTFB) là một chỉ số rõ ràng nhất về hiệu quả của cache.
2. Giám sát tài nguyên máy chủ:
Cache không chỉ làm web nhanh hơn mà còn giảm tải cho máy chủ. Hãy sử dụng các công cụ giám sát hệ thống như htop, top, hoặc các nền tảng giám sát chuyên nghiệp (như New Relic, Datadog) để theo dõi các chỉ số quan trọng trước và sau khi triển khai cache, đặc biệt là trong giờ cao điểm.
- Tải CPU (CPU Load): Bạn sẽ thấy tải CPU trung bình giảm xuống rõ rệt vì Nginx không còn phải đợi PHP hay các ứng dụng backend khác xử lý.
- Sử dụng RAM: Mức tiêu thụ bộ nhớ của các tiến trình ứng dụng (như PHP-FPM) cũng sẽ giảm.
- Băng thông nội bộ: Lưu lượng mạng giữa Nginx và máy chủ backend giảm, vì hầu hết các yêu cầu được xử lý ngay tại Nginx.
Việc so sánh các số liệu này sẽ cung cấp bằng chứng xác thực về lợi ích mà Nginx cache mang lại cho toàn bộ hạ tầng của bạn.

Mẹo tối ưu và xử lý sự cố liên quan đến cache trong Nginx
Xử lý cache không được lưu hoặc không tái sử dụng
Một trong những vấn đề phổ biến nhất khi mới cấu hình cache là nội dung không được lưu như mong đợi, bạn luôn nhận được trạng thái MISS hoặc BYPASS. Dưới đây là một số nguyên nhân và cách khắc phục.
1. Kiểm tra Headers từ Backend:
Nginx rất tôn trọng các header điều khiển cache được gửi từ máy chủ backend. Nếu ứng dụng của bạn (ví dụ: WordPress, Laravel) gửi các header như Cache-Control: no-cache, no-store, must-revalidate hoặc Pragma: no-cache, Nginx sẽ không lưu phản hồi đó.
- Cách kiểm tra: Dùng
curl -I https://yourdomain.comđể xem các header phản hồi. - Cách khắc phục: Bạn có thể cấu hình ứng dụng backend để không gửi các header này cho nội dung công khai. Hoặc, bạn có thể buộc Nginx bỏ qua chúng bằng chỉ thị
proxy_ignore_headershoặcfastcgi_ignore_headers.proxy_ignore_headers Cache-Control Pragma;fastcgi_ignore_headers Cache-Control Pragma;
Hãy sử dụng tùy chọn này một cách cẩn thận vì nó có thể ghi đè lên các hành vi cache quan trọng của ứng dụng.
2. Lỗi Cấu hình Bỏ qua Cache:
Các điều kiện if và các chỉ thị *_cache_bypass có thể là thủ phạm. Hãy kiểm tra lại logic của bạn. Ví dụ, một điều kiện quá rộng như if ($query_string) có thể khiến tất cả các trang có tham số (kể cả các tham số tracking vô hại như utm_source) đều bị bỏ qua cache.
3. Vấn đề về Cookie:
Nginx có thể được cấu hình để không cache các yêu cầu có chứa một số cookie nhất định. Ví dụ, proxy_cache_bypass $http_cookie sẽ bỏ qua cache cho mọi yêu cầu có cookie. Hãy đảm bảo logic của bạn chỉ nhắm đến các cookie cụ thể, ví dụ như cookie phiên đăng nhập.
4. Kích thước Phản hồi:
Mặc định, Nginx chỉ cache các phản hồi có kích thước nhỏ. Nếu bạn có các trang HTML lớn, bạn có thể cần tăng giới hạn bằng các chỉ thị proxy_buffer_size và proxy_buffers.
Khắc phục lỗi cache xung đột, dữ liệu cũ hiển thị
Vấn đề ngược lại là khi cache hoạt động quá “tốt”, khiến người dùng nhìn thấy nội dung cũ hoặc thậm chí là nội dung không dành cho họ.
1. Thiết lập Cache Key không hợp lý:
proxy_cache_key hoặc fastcgi_cache_key là yếu tố quyết định tính duy nhất của một đối tượng trong cache. Nếu key quá chung chung, các trang khác nhau có thể bị ghi đè lên nhau.
- Ví dụ: Nếu bạn chỉ dùng
$host$request_urilàm key, phiên bản di động và máy tính của cùng một URL có thể bị lẫn lộn nếu trang web của bạn sử dụng user-agent để hiển thị nội dung khác nhau. - Cách khắc phục: Thêm các biến liên quan vào key. Ví dụ, để phân biệt cache cho phiên bản mobile và desktop, bạn có thể thêm một biến custom vào key:
# Thêm biến $is_mobile vào keyfastcgi_cache_key "$scheme$request_method$host$request_uri$is_mobile";
2. Cache nội dung cá nhân hóa:
Tuyệt đối không cache các trang chứa thông tin cá nhân của người dùng, như trang “Tài khoản của tôi”, giỏ hàng, hoặc các trang sau khi đăng nhập.
- Cách khắc phục: Sử dụng logic
*_cache_bypassdựa trên cookie đăng nhập. Cấu hình ví dụ cho WordPress ở trên đã xử lý vấn đề này bằng cách kiểm tra cookiewordpress_logged_in_. Tương tự, bạn cần xác định cookie phiên của ứng dụng web của mình và tạo quy tắc bỏ qua cache tương ứng.
3. Vệ sinh cache thủ công:
Khi bạn đã xác định được một nội dung bị cache sai, hãy sử dụng các phương pháp xóa cache (purge) đã đề cập ở phần trước để loại bỏ nó ngay lập tức. Đảm bảo rằng plugin hoặc công cụ triển khai của bạn được tích hợp với cơ chế xóa cache của Nginx để tự động hóa quy trình này.

Các phương pháp tối ưu và thực tiễn tốt nhất
Để khai thác tối đa sức mạnh của Nginx cache, việc tuân thủ các thực tiễn tốt nhất là vô cùng cần thiết. Dưới đây là những mẹo và chiến lược giúp bạn xây dựng một hệ thống cache hiệu quả, an toàn và dễ quản lý.
1. Sử dụng cache cho các tài nguyên tĩnh và động phù hợp:
Không phải tất cả nội dung đều nên được cache như nhau. Hãy phân loại và áp dụng chiến lược riêng:
- Tài nguyên tĩnh (CSS, JS, Hình ảnh, Fonts): Đây là những ứng cử viên hoàn hảo cho việc cache dài hạn. Chúng hiếm khi thay đổi. Bạn có thể tự tin đặt thời gian hết hạn cache dài (vài tuần hoặc vài tháng) cho chúng thông qua
expiresdirective trong mộtlocationblock riêng.location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ {
expires 30d;
add_header Cache-Control "public";
} - Tài nguyên động (HTML): Đây là các trang được tạo ra bởi backend. Hãy đặt thời gian cache ngắn hơn (từ vài phút đến vài giờ) tùy thuộc vào tần suất nội dung của bạn thay đổi.
2. Cấu hình giới hạn dung lượng cache hiệu quả:
Sử dụng tham số max_size trong proxy_cache_path hoặc fastcgi_cache_path để giới hạn tổng dung lượng cache trên đĩa. Điều này ngăn cache chiếm hết dung lượng ổ cứng của bạn. Khi đạt đến giới hạn, Nginx sẽ tự động xóa các mục ít được sử dụng nhất để nhường chỗ cho nội dung mới (cơ chế LRU – Least Recently Used).
3. Tránh cache những trang không nên cache:
Đây là quy tắc vàng để tránh các vấn đề bảo mật và trải nghiệm người dùng tồi tệ. Luôn luôn loại trừ các trang sau khỏi bộ nhớ đệm:
- Trang quản trị (ví dụ:
/wp-admin/trong WordPress) - Trang giỏ hàng và thanh toán trong các website thương mại điện tử
- Các trang hồ sơ người dùng, trang “Tài khoản của tôi”
- Kết quả tìm kiếm hoặc các trang có tính tương tác cao, phụ thuộc vào tham số truy vấn.
Sử dụng các quy tắc if và *_cache_bypass một cách cẩn thận để đảm bảo các trang này luôn được phục vụ trực tiếp từ backend.
4. Thường xuyên kiểm tra log và điều chỉnh cấu hình:
Hiệu suất cache không phải là thứ “cài đặt một lần rồi quên”. Hãy thêm biến $upstream_cache_status vào định dạng log của Nginx để có thể phân tích tỷ lệ HIT/MISS theo thời gian.log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'cache_status: $upstream_cache_status';
access_log /var/log/nginx/access.log main;
Dựa trên dữ liệu log, bạn có thể điều chỉnh thời gian hết hạn cache, tinh chỉnh các quy tắc bỏ qua, hoặc tăng dung lượng cache nếu cần thiết.
5. Không thiết lập thời gian cache quá lâu một cách mù quáng:
Mặc dù việc cache trong thời gian dài giúp tăng tỷ lệ HIT, nó cũng làm tăng nguy cơ người dùng thấy nội dung lỗi thời. Hãy tìm điểm cân bằng hợp lý. Đối với các nội dung quan trọng, việc sử dụng cơ chế xóa cache (purge) chủ động khi có cập nhật sẽ hiệu quả hơn là chỉ dựa vào thời gian hết hạn.

Kết luận
Qua hướng dẫn chi tiết này, chúng ta có thể thấy rõ vai trò không thể thiếu của cache trong việc xây dựng một website hiệu suất cao. Việc cấu hình cache trên Nginx, dù là proxy_cache hay fastcgi_cache, đều là một trong những phương pháp tối ưu hiệu quả nhất để tăng tốc độ tải trang, giảm tải cho máy chủ và cải thiện đáng kể khả năng chịu tải của hệ thống. Từ việc giảm độ trễ cho người dùng cuối đến việc tiết kiệm tài nguyên phần cứng, lợi ích mà Nginx cache mang lại là vô cùng to lớn.
Chúng tôi khuyến khích bạn bắt đầu áp dụng các kỹ thuật này vào hệ thống của mình. Hãy lựa chọn giữa proxy_cache cho các ứng dụng đa dạng và fastcgi_cache cho các trang web dựa trên PHP để phù hợp nhất với nhu cầu thực tế. Đừng ngần ngại thử nghiệm với các cấu hình, bắt đầu với thời gian cache ngắn, sau đó theo dõi và tinh chỉnh liên tục. Việc kiểm tra trạng thái cache qua header, phân tích log và đo lường hiệu suất sẽ giúp bạn tìm ra thiết lập tối ưu nhất cho trang web của mình.
Thế giới web không ngừng phát triển, và Nginx cũng vậy. Hãy luôn cập nhật các tài liệu chính thức và theo dõi các bản phát hành mới của Nginx, vì chúng thường đi kèm với những cải tiến về hiệu suất và các tính năng cache mới. Bằng việc làm chủ công cụ mạnh mẽ này, bạn đang trao cho website của mình một lợi thế cạnh tranh quan trọng: tốc độ và sự ổn định.