GIẢI BÀI TOÁN TRA CỨU KHOẢNG CÁCH PICKUP LOCATIONS TRONG CACHE: TỐI ƯU HÓA HIỆU NĂNG DATABASE
1. Nỗi Đau Hệ Thống: Khi Địa Lý Không Thể Query Bừa Bãi
Hãy tưởng tượng hệ thống của bạn có 10.000 điểm đón (pickup locations) cố định trong thành phố.
Nếu tính toán khoảng cách trực tiếp trên Database (ví dụ dùng hàm hình học không gian ST_Distance của MySQL/PostgreSQL hoặc tính toán bằng công thức Haversine trong SQL), mỗi query sẽ ép Database phải quét qua hàng nghìn dòng dữ liệu, tính toán lượng giác phức tạp trên từng record.
Khi lượng truy cập đạt 5.000 request/giây, CPU của Database Server sẽ chạm ngưỡng 100%, độ trễ (latency) tăng vọt từ vài mili-giây lên hàng giây, dẫn đến trải nghiệm tồi tệ cho người dùng.
Bản chất vấn đề: Khoảng cách giữa hai điểm đón cố định A và B là một hằng số địa lý, nó không bao giờ thay đổi. Việc đi tính toán lại từ đầu hoặc query database cho một giá trị đã biết sẵn là một sự lãng phí tài nguyên khủng khiếp.
2. Tư Duy Thiết Kế Giải Pháp: Cache-Aside kết hợp Redis
Để tối ưu hóa, chúng ta sẽ áp dụng chiến lược đưa toàn bộ ma trận khoảng cách hoặc tra cứu nhanh vào bộ nhớ RAM thông qua Redis Cache, kết hợp cấu trúc lưu trữ thông minh.
Bước 1: Chuẩn hóa định danh tọa độ (Key Generation)
Để tra cứu khoảng cách giữa điểm (Vĩ độ , Kinh độ ) và điểm (, ), chúng ta cần tạo ra một chiếc khóa (Key) duy nhất trong Cache.
Vì phép tính khoảng cách từ cũng chính bằng , để tránh việc lưu trùng lặp 2 chiều, ta sắp xếp tọa độ sao cho điểm có ID nhỏ hơn luôn đứng trước:
Cache Key: distance:loc_<id_1>:loc_<id_2>
Ví dụ: distance:loc_105:loc_208
(Trường hợp điểm đón là tọa độ tự do không có ID sẵn, ta có thể làm tròn đến 3-4 chữ số thập phân để gom nhóm các điểm gần nhau, hoặc sử dụng Geohash).
Bước 2: Ứng dụng chiến lược Cache-Aside (Lazy Loading)
Khi một service cần tra cứu khoảng cách giữa hai điểm đón:
- Kiểm tra Cache (Redis): Hệ thống băm tọa độ/ID thành key và tra cứu trong Redis bằng lệnh
GET. - Cache Hit (Có dữ liệu): Redis trả về kết quả ngay lập tức trong vòng mili-giây. Hoàn tất!
- Cache Miss (Không tìm thấy):
- Hệ thống mới gọi vào Database (hoặc dịch vụ tính toán toán học) để tính khoảng cách 1 lần duy nhất.
- Lưu kết quả đó ngược lại vào Redis với lệnh
SET(có thể gán thời gian sống TTL hoặc lưu vĩnh viễn vì khoảng cách địa lý không đổi). - Trả kết quả về cho client.
3. Hiện Thực Hóa Bằng Mã Nguồn (Ví dụ mô phỏng Node.js)
Dưới đây là mô hình logic xử lý việc tra cứu khoảng cách sử dụng Redis làm tầng đệm:
const Redis = require('ioredis');
const redis = new Redis();
async function getPickupDistance(locA, locB) {
// 1. Chuẩn hóa Key để đảm bảo tính đối xứng (A->B cũng là B->A)
const [first, second] = locA.id < locB.id ? [locA, locB] : [locB, locA];
const cacheKey = `dist:loc_${first.id}:loc_${second.id}`;
// 2. Tra cứu trong Cache (Redis)
let cachedDistance = await redis.get(cacheKey);
if (cachedDistance !== null) {
// Cache Hit: Trả về trực tiếp, không chạm Database!
return parseFloat(cachedDistance);
}
// 3. Cache Miss: Tính toán từ thuật toán hoặc truy vấn DB
const calculatedDistance = calculateHaversineDistance(
first.lat, first.lng,
second.lat, second.lng
);
// 4. Lưu lại vào Cache để phục vụ cho các lần gọi sau (Lưu trữ 24h hoặc vĩnh viễn)
await redis.set(cacheKey, calculatedDistance, 'EX', 86400);
return calculatedDistance;
}
4. Giải Pháp Nâng Cao Cho Hệ Thống Quy Mô Lớn (Pre-warming Cache)
Nếu hệ thống của bạn có danh sách điểm đón cố định (ví dụ 5.000 điểm đón của một hãng xe tại TP.HCM), việc chờ người dùng search rồi mới cache (Lazy Loading) sẽ khiến các request đầu tiên bị chậm (hiện tượng Cache Cold).
Kỹ thuật tối ưu cấp cao - Cache Pre-warming (Làm ấm bộ nhớ đệm):
Vào thời điểm hệ thống khởi động hoặc chạy ngầm qua một Cron Job định kỳ thấp điểm, ta viết một script chạy nền (Background Worker) quét qua toàn bộ các điểm đón, tính toán trước ma trận khoảng cách và MSET (Multi-set) toàn bộ vào Redis.
Lúc này, 100% các request tra cứu của người dùng sẽ đọc trực tiếp từ RAM, giải phóng hoàn toàn áp lực cho Database.
💡 Lời Kết
Giải quyết bài toán tra cứu khoảng cách pickup locations không nằm ở việc viết câu lệnh SQL thông minh đến đâu, mà nằm ở tư duy giảm thiểu số lần chạm Database. Bằng cách tận dụng tốc độ đọc ghi tính bằng microsecond của Redis Cache kết hợp chiến lược chuẩn hóa Key đối xứng, bạn đã biến một tác vụ gây nghẽn cổ chai hệ thống thành một thao tác nhẹ nhàng, mượt mà và chịu tải cực lớn.
All Rights Reserved