Trong bài viết lần này mình sẽ viết về kỹ thuật caching nói chung và Redis nói riêng, sau đó sẽ hiện thực một ví dụ về sử dụng Redis với NodeJS.
Nội dung của bài viết gồm 3 phần
Khi sử dụng cache: Với request đầu tiên, cũng mất 10s để thực hiện, nhưng đồng thời lúc này server lưu kết quả truy vấn ở cache nhằm phục vụ cho các request sau. Ở các request tiếp theo, thì server không cần query DB để lấy dữ liệu mà chỉ cần load từ cache ra và trả về cho server; quá trình này tất nhiên có thời gian thực hiện thấp hơn 10s, giả sử cho rằng 7s. Khi đó ta có tổng thời gian cho 30 request là: 10*1 + 7*29 = 213s = 3.55min
Như ta thấy, với việc sử dụng cache thì ta tiết kiệm được tới 87s (gần 1.5min). Hãy tưởng tưởng những con số này được scale up lên thì thời gian và chi phí tiết kiệm được là hiệu quả cỡ nào
Sau khi tìm hiểu cách hoạt động của kĩ thuật caching, tiếp theo chúng ta sẽ tìm hiểu xem Redis là gì?
Redis lưu trữ dữ liệu trên RAM dưới dạng key-value, rất dễ dàng và nhanh chóng truy xuất dữ liệu vì nó không có những ràng buộc phức tạp hay những thao tác khác làm tăng thời gian truy vấn dữ liệu.
Ngoài ra, Redis còn có cơ chế sao lưu dữ liệu lên ổ cứng nhằm khôi phục hệ thống khi xảy ra sự cố
22353:C 18 Apr 2019 20:00:22.089 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 22353:C 18 Apr 2019 20:00:22.089 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=22353, just started 22353:C 18 Apr 2019 20:00:22.089 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf 22353:M 18 Apr 2019 20:00:22.091 * Increased maximum number of open files to 10032 (it was originally set to 8096). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.4 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 22353 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 22353:M 18 Apr 2019 20:00:22.092 # Server initialized 22353:M 18 Apr 2019 20:00:22.092 * Ready to accept connections
Như vậy là chúng ta đã cài đặt thành công Redis trên máy và bây giờ có thể tiến hành demo thực tế xem Redis hoạt động ra sao.
Chúng ta tiến hành cài đặt các package này vào project như sau
Nội dung của bài viết gồm 3 phần
- Giới thiệu: Caching là gì? Redis là gì?
- Cách cài đặt và sử dụng Redis trong quá trình lập trình
- Demo
Chúng ta bắt đầu thôi!
1.Giới thiệu: Caching là gì? Redis là gì?
Caching technique
Đầu tiên chúng ta sẽ tìm hiểu xem Caching technique là gì?
Caching là quá trình lưu trữ dữ liệu ở cache - một loại bộ nhớ tạm. Cache là một loại data store tạm, giúp truy cập dữ liệu rất nhanh chóng và dễ dàng, ngược lại với permanent data store (nằm ở service khác) nhưng truy cập lâu hơn và tốn nhiều tài nguyên hơn.
Cách hoạt động của cache
Theo cách hoạt động thông thường: Mỗi lần client request đến server, server sẽ thực hiện câu truy vấn đến DB và chờ DB trả về kết quả, sau đó xử lý kết quả truy vấn đó và trả về thông tin cho client.
Giả sử mỗi request tốn 10s để thực hiện, và client thực hiện liên tục 30 request, khi đó sẽ mất tổng thời gian là 10*30 = 300 s = 5 min
Thông thường |
With cache |
Sau khi tìm hiểu cách hoạt động của kĩ thuật caching, tiếp theo chúng ta sẽ tìm hiểu xem Redis là gì?
Redis
Theo định nghĩa từ trang chủ
Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.Redis là một cấu trúc lưu trữ dữ liệu trên bộ nhớ, nguồn mở, được sử dụng như DB, bộ nhớ đệm hay message broker. Đồng thời, Redis hỗ trợ nhiều kiểu dữ liệu như: strings, hashes, lists, sets và sorted sets
Redis lưu trữ dữ liệu trên RAM dưới dạng key-value, rất dễ dàng và nhanh chóng truy xuất dữ liệu vì nó không có những ràng buộc phức tạp hay những thao tác khác làm tăng thời gian truy vấn dữ liệu.
Ngoài ra, Redis còn có cơ chế sao lưu dữ liệu lên ổ cứng nhằm khôi phục hệ thống khi xảy ra sự cố
2. Cách cài đặt và sử dụng Redis
Để cài đặt Redis trên máy tính của mình, bạn có thể tải Redis installer tại đây. Sau đó làm theo hướng dẫn để cài đặt. Nếu bạn dùng MacOS bạn có thể cài Redis qua homebrew bằng cách như sau:
brew install redis
Sau khi cài đặt xong, ta tiến hành mở server redis và test thử xem cài đặt thành công hay chưa bằng lệnh
redis-serverKhi thấy kết quả như dưới đ ây là bạn đã cài đặt thành công
22353:C 18 Apr 2019 20:00:22.089 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo 22353:C 18 Apr 2019 20:00:22.089 # Redis version=5.0.4, bits=64, commit=00000000, modified=0, pid=22353, just started 22353:C 18 Apr 2019 20:00:22.089 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf 22353:M 18 Apr 2019 20:00:22.091 * Increased maximum number of open files to 10032 (it was originally set to 8096). _._ _.-``__ ''-._ _.-`` `. `_. ''-._ Redis 5.0.4 (00000000/0) 64 bit .-`` .-```. ```\/ _.,_ ''-._ ( ' , .-` | `, ) Running in standalone mode |`-._`-...-` __...-.``-._|'` _.-'| Port: 6379 | `-._ `._ / _.-' | PID: 22353 `-._ `-._ `-./ _.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | http://redis.io `-._ `-._`-.__.-'_.-' _.-' |`-._`-._ `-.__.-' _.-'_.-'| | `-._`-._ _.-'_.-' | `-._ `-._`-.__.-'_.-' _.-' `-._ `-.__.-' _.-' `-._ _.-' `-.__.-' 22353:M 18 Apr 2019 20:00:22.092 # Server initialized 22353:M 18 Apr 2019 20:00:22.092 * Ready to accept connections
Như vậy là chúng ta đã cài đặt thành công Redis trên máy và bây giờ có thể tiến hành demo thực tế xem Redis hoạt động ra sao.
3. Demo
Trong ví dụ thực tế này mình sẽ viết 1 API fetch data về với số lượng lớn và sử dụng cache để xem nó tiết kiệm thời gian của chúng ta như thế nào. API của chúng ta rất đơn giản, chỉ có 1 route duy nhất là /photos để lấy danh sách rầt nhiều ảnh về và trả về dạng json.
Ảnh sẽ được fetch về từ đây: https://jsonplaceholder.typicode.com/photos
Chúng ta bắt đầu!
Ảnh sẽ được fetch về từ đây: https://jsonplaceholder.typicode.com/photos
Chúng ta bắt đầu!
Khởi tạo
Đầu tiên tạo 1 thư mục project với tên ví dụ như: redis-nodejs-demo
Trong thư mục này, mở terminal và gõ lệnh sau để khởi tạo project
npm init --forceTiếp theo tạo 1 file index.js, và ta sẽ thực hiện code trong file này
Cài đặt các package cần thiết
Để thực hiện demo này ta cần một số các npm package như sau:
- express: để tạo HTTP server cho API và xử lý routing
- redis: Nodejs client của redis
- axios: Giúp gọi API qua các HTTP request
- response-time: Ghi lại thời gian thực hiện request vào header (dùng để so sánh thời gian xử lý giữa có cache và không có cache)
npm install --save axios express redis response-time
Ok, sau khi chuẩn bị xong chúng ta tiến hành code
Coding
Trong file index.js ta sử thêm code như sau
const express = require('express');
const responseTime = require('response-time')
const axios = require('axios');
const redis = require('redis');
const app = express();
const client = redis.createClient();
// Print redis errors to the console
client.on('error', (err) => {
console.log("Error " + err);
});
// use response-time as a middlewar
app.use(responseTime());
const PHOTO_REDIS_KEY = 'cache:photos';
const URL = 'https://jsonplaceholder.typicode.com/photos';
app.get('/photos', async (req, res) => {
return client.get(PHOTO_REDIS_KEY, async (error, photos) => {
if (error) {
res.json(err)
}
if (photos) {
res.json({
source: 'cache',
data: JSON.parse(photos),
});
} else {
const { data } = await axios.get(URL);
client.setex(PHOTO_REDIS_KEY, 3600, JSON.stringify(data))
res.json({
source: 'api',
data
})
}
})
});
app.listen(3000, () => {
console.log('Server listening on port: ', 3000)
});
Ta thấy, trước khi trả về kết quả, thay vì ngay lập tức gọi API, ta sẽ lấy dữ liệu từ cache trước thông qua client.get(KEY, callback), trong lúc này nếu trong cache có dữ liệu rồi thì ta chỉ việc lấy lên và trả về kết quả. Nếu trong cache không có dữ liệu (lần đầu fetch dữ liệu hoặc khi cache đã expire) thì ta mới gọi đến API để lấy dữ liệu thông qua axios.
Lúc này khi dữ liệu được lấy về từ API, ta tiến hành lưu nó vào cache bằng client.setex(KEY, ExpireTime, data) để lần tiếp theo gọi thì lấy dữ liệu từ cache.
Lúc này khi dữ liệu được lấy về từ API, ta tiến hành lưu nó vào cache bằng client.setex(KEY, ExpireTime, data) để lần tiếp theo gọi thì lấy dữ liệu từ cache.
Test kết quả:
Sau khi code xong, ta chạy lệnh sau để chạy server
Như các bạn có thể thấy, trong lần đầu tiên, chúng ta mất tới 2567ms để fetch dữ liệu và nguồn dữ liệu được lấy bằng viẹc gọi API như trên hình.
node index.jsTiếp theo chúng ta dùng Postman để xem kết quả. Trong Postman thực hiện một GET request đến http://localhost:3000/photos và xem kết quả
Without cache |
Tiếp theo, ta thực hiện lại request này một lần nữa và xem điều kì diệu
With cache |
Ở lần thứ hai này chúng ta có thể thấy kết qủa cực kì ấn tượng, chỉ mất 52ms để trả về dữ liệu từ cache (nhanh gấp ~50 lần so với fetch API)
Kết
Vậy là chúng ta đã tìm hiểu về Redis và thực hiện xong ví dụ về Cache để thấy được sự hiệu quả mà nó đem lại. Hi vọng bài viết này có thể giúp các bạn sử dụng cache tốt hơn trong quá trình làm việc của mình. Nếu thấy bài viết hay và có ích hãy chia s ẻ cho mọi người cùng biết, nếu các bạn có bất kì ý kiến đóng góp nào thì đừng ngần ngại để lại bình luận ở cuối bài viết nhé. ThanksReference
- Redis documentation: https://redis.io/documentation
Advertisement