Redis 是一個開源的 記憶體內 (In-Memory) 資料結構儲存系統,通常被當作資料庫、快取和訊息代理 (Message Broker) 來使用。
因此,我們通常不會把使用者的訂單或密碼單獨存在 Redis,而是把它當作傳統資料庫前面的「擋箭牌 (快取)」。
當前端發送 API 請求來查詢「今日熱門商品」時:
步驟 1:安裝 Redis 客戶端
npm install redis
(備註:實務上你需要有一台 Redis 伺服器。你可以註冊免費的 Redis Cloud,或是明天我們會教你用 Docker 在電腦上一鍵啟動!今天先看懂程式碼邏輯。)
步驟 2:實作快取 API
我們來寫一支查詢使用者資料的 API,體驗加入 Redis 前後的差異:
import express from 'express';
import { createClient } from 'redis';
const app = express();
// 1. 建立並連線到 Redis (請填入你的 Redis 網址)
const redisClient = createClient({
url: 'redis://default:你的密碼@你的Redis伺服器位址:6379'
});
redisClient.on('error', (err) => console.log('Redis 連線錯誤', err));
await redisClient.connect();
console.log(' 成功連線至 Redis!');
// 模擬一個非常耗時的資料庫查詢 (例如要花 3 秒鐘)
const slowDatabaseQuery = async (userId) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id: userId, name: 'Bibo', title: '全端工程師' });
}, 3000);
});
};
// 2. 撰寫帶有快取機制的 API
app.get('/api/users/:id', async (req, res) => {
const { id } = req.params;
const cacheKey = `user_profile_${id}`; // 定義專屬的 Redis Key
try {
// 步驟 A:先去 Redis 找找看有沒有快取 (Cache Hit)
const cachedData = await redisClient.get(cacheKey);
if (cachedData) {
console.log(' 從 Redis 快取神速讀取!');
// 注意:Redis 只能存字串,所以存入時要轉 JSON 字串,拿出來時要轉回 Object
return res.json(JSON.parse(cachedData));
}
// 步驟 B:Redis 沒有 (Cache Miss),只好去查真的資料庫
console.log('🐢 找不到快取,正在進行緩慢的資料庫查詢...');
const userData = await slowDatabaseQuery(id);
// 步驟 C:查到資料後,把它存進 Redis,並設定過期時間 (EX: 3600 秒 = 1 小時)
await redisClient.set(cacheKey, JSON.stringify(userData), {
EX: 3600
});
res.json(userData);
} catch (error) {
res.status(500).json({ error: '伺服器錯誤' });
}
});
app.listen(3000, () => console.log('伺服器啟動於 PORT 3000'));
測試結果:
當你的流量大到需要開 3 台 Node.js 伺服器來分擔時,這稱為「水平擴展 (Horizontal Scaling)」。
但還記得昨天的 Socket.io 嗎?如果 A 使用者連到 1 號伺服器,B 使用者連到 2 號伺服器,他們即使加入同一個房間,也收不到對方的訊息!因為 Socket.io 的記憶體是互相獨立的。
這時候 Redis 又要出來拯救世界了!透過設定 Redis Adapter,我們可以讓這 3 台 Node.js 伺服器透過 Redis 來互相溝通 (Pub/Sub 機制)。1 號伺服器收到訊息後,會丟給 Redis,Redis 再廣播給 2 號和 3 號伺服器,完美解決多台伺服器之間的 WebSocket 即時通訊問題!這就是微服務架構中不可或缺的底層拼圖。