Redis là một kho lưu trữ dữ liệu chủ yếu lưu trữ dữ liệu trong bộ nhớ. Nó nhanh hơn cơ sở dữ liệu truyền thống và đã trở nên khá phổ biến.
Trong hướng dẫn này, bạn sẽ tìm hiểu những kiến thức cơ bản về cách hoạt động của Redis, thời điểm sử dụng, cách cài đặt Redis trên thiết bị của bạn và cách sử dụng Redis làm hệ thống bộ nhớ đệm trong ứng dụng web PHP.
Redis là gì?
Redis là một kho lưu trữ dữ liệu – giống như một cơ sở dữ liệu, nhưng lưu trữ dữ liệu chủ yếu trong bộ nhớ. Điều này làm cho nó nhanh hơn nhiều so với cơ sở dữ liệu truyền thống nơi dữ liệu được lưu trữ trên đĩa. Vì tốc độ này nên Redis thường được sử dụng làm công cụ lưu vào bộ nhớ đệm.
Redis có thể lưu trữ dữ liệu ở bất kỳ loại dữ liệu nào vì nó sử dụng hệ thống cặp khóa-giá trị để lưu trữ dữ liệu. Điều này cũng không giống như cơ sở dữ liệu truyền thống sử dụng tài liệu hoặc hàng.
Bạn có thể coi cơ sở dữ liệu Redis như một đối tượng JSON lớn, trong đó mọi thứ trong cơ sở dữ liệu là một cặp khóa-giá trị. Điều này có nghĩa đây có thể không phải là nơi tốt nhất để lưu trữ dữ liệu có cấu trúc.
Bạn cũng có thể sử dụng Redis làm cơ sở dữ liệu vì nó có khả năng ghi dữ liệu vào đĩa để duy trì. Bạn có thể định cấu hình Redis để lưu trữ dữ liệu theo định kỳ hoặc sau mỗi lệnh bạn đưa ra. Khi Redis không được định cấu hình để duy trì dữ liệu, nó rất dễ biến động và hệ thống gặp sự cố sẽ dẫn đến mất dữ liệu.
Redis phổ biến trong các ứng dụng cấp sản xuất và được các công ty lớn như Twitter, Github, SnapChat và StackOverFlow sử dụng.
- Dành cho mật khẩu dùng một lần (OTP):Những mật khẩu này thường được tạo để sử dụng một lần và có thời gian tồn tại ngắn. Với khả năng đặt ngày hết hạn cho dữ liệu của Redis, bạn có thể lưu trữ OTP một cách an toàn mà không cần lo lắng về việc xóa chúng sau một khoảng thời gian nhất định.
- Đối với các tài nguyên được truy cập thường xuyên:Đối với dữ liệu không thay đổi quá thường xuyên nhưng được truy cập nhiều, bạn có thể sử dụng Redis để tiết kiệm thời gian lẽ ra phải dùng để truy vấn cơ sở dữ liệu hoặc thực hiện cuộc gọi đến một số dịch vụ bên ngoài.
- Đối với các truy vấn nặng:Đối với các truy vấn cơ sở dữ liệu tốn thời gian và cũng không thay đổi quá thường xuyên, hãy sử dụng Redis để giảm thời gian này bằng cách lưu trữ kết quả bao lâu tùy thích.
Cách cài đặt Redis
Bạn có thể cài đặt Redis trên bất kỳ hệ điều hành nào. Dưới đây là hướng dẫn dành cho macOS, Hệ thống con Windows dành cho Linux và Linux.
macOS
Để cài đặt Redis trên macOS, hãy chạy:
brew install redis
Sau đó, chạy lệnh này để khởi động Redis:
redis-server
Hệ thống con Windows cho Linux và Linux
Redis chưa hỗ trợ chính xác hệ điều hành Windows, vì vậy bạn có thể cài đặt WSL (Hệ thống con Windows cho Linux) trên windows để có môi trường Linux.
Để cài đặt Redis trên Linux, hãy chạy:
curl -fsSL https://packages.redis.io/gpg | sudo gpg --dearmor -o /usr/share/keyrings/redis-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/redis-archive-keyring.gpg] https://packages.redis.io/deb $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/redis.list
sudo apt-get update
sudo apt-get install redis
Sau đó, chạy lệnh này để khởi động Redis:
sudo service redis-server start
Bây giờ Redis đã được cài đặt, bạn có thể kiểm tra nó bằng cách chạy redis-cli ping . Điều này sẽ xuất ra "PONG" . Như thế này:
Kiểm tra cài đặt Redis
Cơ bản về Redis
Để sử dụng Redis dưới dạng REPL hoặc dưới dạng ứng dụng độc lập, hãy chạy redis-cli . Nó sẽ mở môi trường REPL.
Cách thiết lập dữ liệu
Sử dụng SET từ khóa để đặt cặp giá trị khóa trong Redis. Để đặt username khóa tới giá trị Zubs , hãy chạy cái này:
SET username Zubs
Đặt cặp khóa-giá trị
Cách lấy dữ liệu
Để lấy username đã lưu gần đây phím, hãy sử dụng GET từ khóa như thế này:
GET username
Lấy giá trị bằng khóa
Cách xóa dữ liệu
Bạn cũng có thể xóa khóa đã lưu trước đó bằng DEL từ khóa như thế này:
DEL username
Xóa giá trị bằng khóa
Cách kiểm tra xem giá trị có tồn tại hay không
Bạn có thể kiểm tra sự tồn tại của khóa bằng cách sử dụng EXISTS từ khóa. Nó trả về 0 khi khóa không tồn tại và 1 nếu có. Bạn có thể kiểm tra bằng cách kiểm tra xem username đã xóa gần đây hay chưa chìa khóa tồn tại. Như thế này:
Cách đặt thời gian tồn tại cho chìa khóa
Redis cho phép bạn chỉ định thời gian tồn tại của một số khóa khi tạo nó. Đây là một tính năng thực sự tuyệt vời của Redis. Để thực hiện việc này, hãy sử dụng SETEX từ khóa như thế này:
SETEX key seconds value
Bạn có thể kiểm tra thời gian tồn tại của một khóa cụ thể bằng cách sử dụng TTL từ khóa. Điều này trả về -1 nếu khóa không hết hạn, nghĩa là nó sẽ được lưu trữ vô thời hạn. Nó trả về -2 nếu chìa khóa không tồn tại. Và nó trả về thời gian tính bằng giây nếu khóa tồn tại.
Bạn có thể đặt thời gian hết hạn tính bằng giây cho khóa được tạo trước đó mà không có thời gian hết hạn bằng cách sử dụng EXPIRE từ khóa. Ví dụ:tạo khóa để lưu trữ biến age với giá trị là 26 .
SET age 26
Sau đó, đặt thời gian hết hạn là 10 giây cho nó.
EXPIRE age 20
Hãy kiểm tra lại thời gian còn lại để sống lặp đi lặp lại vài lần để xem nó thực sự giảm đi như thế nào và cuối cùng không còn tồn tại nữa.
Cách xây dựng một ứng dụng đơn giản với Redis
Để giúp bạn hiểu cách Redis hoạt động, giờ đây chúng tôi sẽ xây dựng một ứng dụng web cơ bản sử dụng Redis để lưu trữ dữ liệu vào bộ nhớ đệm nhằm tải phản hồi nhanh hơn. Bạn sẽ xây dựng một ứng dụng đơn giản để tìm nạp dữ liệu hình ảnh từ JSONPlaceholder và trả về chúng.
Tạo dự án PHP mới bằng Composer
Tạo một thư mục mới cho dự án, thay đổi thư mục vào thư mục mới tạo và chạy hợp chất sau để tạo dự án soạn thảo mới:
composer init -q
Điều này sẽ tạo ra một composer.json mới tập tin sẽ trông như thế này:
{
"require": {}
}
Tiếp theo, tạo một thư mục chung để chứa các tệp mã công khai của bạn. Sau đó tạo một index.php mới tập tin trong thư mục.
Bây giờ hãy đưa một số nội dung soạn sẵn vào tệp PHP và khởi động máy chủ.
<?php
echo "Hello World!";
php -S localhost:8080
Cài đặt bộ định tuyến đơn giản và xử lý các yêu cầu
Để hoàn thành dự án, hãy cài đặt bộ định tuyến PHP đơn giản, Altorouter và một ứng dụng web, Guzzlehttp .
composer require altorouter/altorouter guzzlehttp/guzzle
Cập nhật index.php để chứa mã này:
<?php
// Import composer autoload file
require_once __DIR__ . '/../vendor/autoload.php';
// Import GuzzleHttp Client
use GuzzleHttp\Client;
// Instantiate router and web client
$router = new AltoRouter();
$client = new Client();
// Register Sample route
$router->map('GET', '/', function () {
// Set response Content-Type
header('Content-Type: application/json; charset=utf-8');
// Return basic response
echo json_encode(['data' => 'Hello World']);
});
/**
* Route to get all photos
*/
$router->map('GET', '/photos', function () use ($client) {
// Make request to JSONPlaceholder
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/photos');
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'data' => json_decode($response->getBody()->getContents())
]);
});
/**
* Route to get single photo by id
*/
$router->map('GET', '/photos/[i:id]', function (int $id) use ($client) {
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/photos/' . $id);
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'data' => json_decode($response->getBody()->getContents())
]);
});
$match = $router->match();
if( is_array($match) && is_callable( $match['target'] ) ) {
call_user_func_array( $match['target'], $match['params'] );
} else {
// no route was matched
header( $_SERVER["SERVER_PROTOCOL"] . ' 404 Not Found');
}
Mã này khá tự giải thích. Tuy nhiên, đây là một sự cố cho rõ ràng. Từ dòng 1-11, các lớp bắt buộc GuzzleHttp và AltoRouter được nhập và khởi tạo.
Từ dòng 14-20, tuyến đường đầu tiên được đăng ký, với kết quả đóng đơn giản trả về "Xin chào thế giới!". Các dòng 25-45 đăng ký thêm hai tuyến, một tuyến để lấy tất cả ảnh, /photos và một cái khác để tìm nạp một bức ảnh, /photos/id .
Các dòng cuối cùng được yêu cầu dựa trên tài liệu của gói bộ định tuyến để thực sự thực thi các phần đóng được đặt trong khai báo tuyến đường.
Bạn có thể kiểm tra các tuyến đường này bằng Postman.
Xin chào tuyến đường thế giới
Lộ trình lấy tất cả ảnh
Nhận một lộ trình chụp ảnh
/photos tuyến mất trung bình 1400ms cho mỗi yêu cầu. /photos/id mất trung bình 900ms cho mỗi yêu cầu.
Cài đặt và khởi tạo Redis
Bạn có thể giảm thời gian này bằng cách lưu kết quả của yêu cầu ban đầu vào JSONPlaceholder, sau đó trả về phản hồi từ bộ nhớ đệm thay vì cứ mỗi lần đưa ra yêu cầu.
Để sử dụng Redis với PHP, hãy cài đặt tiện ích mở rộng PhpRedis. Tiện ích mở rộng này cung cấp API để liên lạc với Redis. Bạn có thể dễ dàng cài đặt nó bằng lệnh:
pecl install redis
Sau khi cài đặt, bạn có thể sử dụng lớp này trong dự án PHP của mình. Nhập lớp và khởi tạo nó ở đầu index.php của bạn tập tin:
$redis = new Redis();
$redis->connect('127.0.0.1');
Sau khi thực hiện việc này, bây giờ bạn có thể sử dụng Redis trong dự án của mình.
Cách lưu vào bộ nhớ đệm dữ liệu bằng Redis
Lưu trữ phản hồi JSON thô được trả về từ JSONPlaceholder tới Redis với thời gian hết hạn là 1 giờ (3600 giây).
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/photos');
$redis->setex(
'photos',
3600,
$response->getBody()->getContents()
);
Tại đây, bạn tạo một key mới có tên là photos , cho nó thời gian hết hạn là 1 giờ, sau đó gán cho nó phản hồi thô nhận được từ JSONPlaceholder.
Nhưng tại thời điểm này API vẫn mất nhiều thời gian để phản hồi. Điều này là do bạn chỉ lưu trữ phản hồi này, bạn không sử dụng Redis để trả về phản hồi.
Để khắc phục điều này, khi có yêu cầu mới, hãy kiểm tra xem bạn có dữ liệu nào được lưu trữ trước đó trong bộ nhớ hay không. Nếu có, bạn trả về dữ liệu trong bộ nhớ, nếu không, bạn sẽ gọi tới JSONPlaceholder.
Cập nhật /photos chặn cái này:
/**
* Route to get all photos
*/
$router->map('GET', '/photos', function () use ($client, $redis) {
// Check if Redis has the key
if (!$redis->exists('photos')) {
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/photos');
// Store the data for next use
$redis->setex(
'photos',
REDIS_STANDARD_EXPIRY,
$response->getBody()->getContents()
);
}
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'data' => json_decode($redis->get('photos'))
]);
});
Thử nghiệm trong Postman để thấy sự cải thiện, bạn thấy thời gian phản hồi trung bình sau cuộc gọi đầu tiên (cuộc gọi ban đầu trước khi được lưu vào bộ nhớ đệm) đã giảm xuống mức trung bình 20 mili giây đối với /photos tuyến đường. Đây là một sự cải tiến hơn 50 lần. Redis tiết kiệm rất nhiều thời gian xử lý và năng lượng.
Cập nhật /photos/id lộ trình sử dụng Redis nữa:
$router->map('GET', '/photos/[i:id]', function (int $id) use ($client, $redis) {
if (!$redis->exists('photos:' . $id)) {
$response = $client->request('GET', 'https://jsonplaceholder.typicode.com/photos/' . $id);
$redis->setex(
'photos:' . $id,
REDIS_STANDARD_EXPIRY,
$response->getBody()->getContents()
);
}
header('Content-Type: application/json; charset=utf-8');
echo json_encode([
'data' => json_decode($redis->get('photos:' . $id))
]);
});
/photos/id Tuyến đường hiện cũng nhanh hơn nhiều vì chỉ mất chưa đến 5 mili giây để nhận được phản hồi, cải thiện hơn 45 lần.
Tóm tắt
Tôi hy vọng bây giờ bạn đã hiểu Redis là gì, những điều cơ bản về nó và cách bạn có thể sử dụng nó để nâng cao tốc độ của các ứng dụng web PHP của mình. Bạn có thể tìm thấy các tệp mã được sử dụng trong bài viết này trên GitHub.
Nếu bạn có bất kỳ câu hỏi hoặc lời khuyên liên quan nào, vui lòng liên hệ với tôi để chia sẻ.
Để đọc thêm các bài viết của tôi hoặc theo dõi công việc của tôi, bạn có thể kết nối với tôi trên LinkedIn, Twitter và Github. Thật nhanh chóng, dễ dàng và miễn phí!
Học cách viết mã miễn phí. Chương trình giảng dạy mã nguồn mở của freeCodeCamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu