近年來,Redis已經成為Node.js應用堆棧中常見的現象。雖然它最流行的用例是緩存,Redis還有很多其他用例,你可以利用它的快閃記憶體資料庫的快得驚人。
在這個教程中,我們將給你一個快速介紹Redis。我們還將使用Redis為節點應用程式創建一個簡單的緩存,看看它是如何影響其性能的。
什麼是Redis
Redis是一個開源的(BSD許可),內存中的數據結構存儲用作資料庫、緩存和消息代理。
您可以將其看作是一個非sql資料庫,它將數據以鍵-值對的形式存儲在系統內存中。如果需要,Redis也支持磁碟持久數據存儲。
Redis支持存儲多種數據結構和數據類型,包括字符串、列表、散列、集合和排序集合。受支持的數據結構為Redis提供了多種用例的通用性。
Redis是最好的情況,在最短的時間需要數據檢索和交付給客戶端。
Redis用例
Redis做緩存
Redis最流行的使用案例之一是緩存。
緩存是什麼
緩存是在緩存中存儲數據副本的過程,以允許應用程式更快地訪問和檢索數據。緩存的目標是比資料庫或遠程伺服器更好地加速數據訪問操作。對於昂貴的(及時的)操作尤其如此。
作為一個後端開發人員,我們的任務是儘快完成客戶的請求。有時候,查詢需要一些操作,比如從資料庫中檢索數據、執行計算、從其他服務中檢索額外數據等等,這些操作會降低我們的性能。
這正是緩存的優勢所在,因為我們可以一次性處理數據,將其存儲在緩存中,然後稍後直接從緩存中檢索數據,而無需執行所有那些昂貴的操作。然後,我們會定期更新緩存,以便用戶可以看到更新的信息。
緩存 & Redis
由於Redis是一個內存資料庫,它的數據訪問操作比任何其他磁碟綁定資料庫可以提供的更快。這使得Redis成為緩存的最佳選擇。它的鍵-值數據存儲是另一個優點,因為它使數據存儲和檢索更加簡單。
在本教程中,我們將看到如何使用Redis和Node.js進行緩存。
Redis實時分析
Redis提供亞毫秒長的數據處理操作。這使得Redis成為依賴於實時數據分析的應用程式的完美候選。
例如,在實施實時欺詐檢測服務時,你可以使用Redis來存儲用戶身份和他們的交易細節。Redis甚至提供了一個ai支持的更快的交易評分系統和更快的統計模型來更好地執行這個用例。
實時分析的其他用例包括實時庫存管理系統和遊戲排行榜。
Redis會話管理
如果您的應用程式使用會話來跟蹤經過身份驗證的用戶並管理用戶特定的數據,那麼Redis非常適合用作會話存儲。使用Redis可以顯著提高系統的性能,同時使其更容易處理用戶的數據,包括憑證,最近的活動,甚至一個類似購物車的系統。
Redis作為一個隊列
你可以使用Redis來對需要很長時間才能完成的應用程式任務進行排隊。您可以實現FIDO(先入先出)隊列或創建延遲隊列,以將任務實現延遲到預定的時間。
緩存節點和Redis
現在,讓我們從本教程的主要重點開始:在NodeJS應用程式中使用Redis進行緩存。
緩存Redis的過程相當簡單。當我們收到用戶對啟用緩存的路由的請求時,我們首先檢查所請求的數據是否已經存儲在緩存中。如果是,我們可以快速檢索數據從Redis和發送響應。
但是,如果數據沒有存儲在緩存中,我們稱之為緩存缺失,我們必須首先從資料庫或外部API檢索數據並將其發送給客戶機。我們還確保將檢索到的數據存儲在緩存中,以便下次收到相同的請求時,可以更快地將緩存的數據發送給用戶。
現在您已經清楚我們要做什麼了,讓我們開始實現。
安裝Redis
如果你還沒有,你需要安裝Redis為本教程。
您可以下載二進位文件並使用以下命令輕鬆地編譯它們。
wget https://download.redis.io/releases/redis-6.0.9.tar.gz
tar xzf redis-6.0.9.tar.gz
cd redis-6.0.9
make
make install
為了確保Redis伺服器沒有問題運行,使用Redis -cli向伺服器發送一個ping。
redis-cli ping
如果你接收到ping作為響應,說明Redis伺服器運行成功。
閱讀官方的快速入門指南,以便更好地了解是否出現了問題。
構建NodeJS應用程式
基本設置
為節點應用程式設置初始樣板,如下所示。
const express = require("express");
const axios = require("axios");
const redis = require("redis");
const app = express();
app.listen(process.env.PORT || 3000, () => {
console.log("Node server started");
});
注意我們是如何使用另外兩個名為axios和redis的包的。redis是標準的redis客戶端為節點。在本教程中,我們使用axios從外部API檢索數據。
在繼續之前,請確保使用npm安裝這兩個包。
npm install axios redis --save
從外部API檢索數據
我們將使用GitHub Jobs API來獲取與世界上不同位置可用的編程任務相關的數據。
您可以將與正在查找的作業相關的搜索詞傳遞給API,並檢索json格式的可用作業數組。對API的示例請求如下所示。
https://jobs.github.com/positions.json?search=node.js
在我們的節點應用程式中,我們定義了一個名為/jobs的路由,它從上面的API檢索作業數據並將其發送回客戶機。
const express = require("express");
const axios = require("axios");
const redis = require("redis");
const app = express();
app.get("/jobs", async (req, res) => {
const searchTerm = req.query.search;
try {
const jobs = await axios.get(`https://jobs.github.com/positions.json?search=${searchTerm}`);
res.status(200).send({
jobs: jobs.data,
});
} catch(err) {
res.status(500).send({message: err.message});
}
});
app.listen(process.env.PORT || 3000, () => {
console.log("Node server started");
});
在這裡,我們使用axios用用戶提供的搜索詞向GitHub Jobs API發送GET請求。
讓我們看看現在郵遞員是如何工作的。
緩存結果
現在,讓我們看看如何通過緩存來提高應用程式的性能。
首先,我們需要通過應用程式連接到Redis伺服器。我們使用已安裝的redis包來完成這個任務。
const redisPort = 6379
const client = redis.createClient(redisPort);
//log error to the console if any occurs
client.on("error", (err) => {
console.log(err);
});
Redis伺服器監聽埠6379在默認。因此,我們傳遞埠號來連接到Redis並創建一個客戶端。
然後,實現從緩存中存儲和檢索數據的邏輯。
app.get("/jobs", (req, res) => {
const searchTerm = req.query.search;
try {
client.get(searchTerm, async (err, jobs) => {
if (err) throw err;
if (jobs) {
res.status(200).send({
jobs: JSON.parse(jobs),
message: "data retrieved from the cache"
});
} else {
const jobs = await axios.get(`https://jobs.github.com/positions.json?search=${searchTerm}`);
client.setex(searchTerm, 600, JSON.stringify(jobs.data));
res.status(200).send({
jobs: jobs.data,
message: "cache miss"
});
}
});
} catch(err) {
res.status(500).send({message: err.message});
}
});
這是怎麼回事?
當我們接收到客戶機對/jobs路由的請求時,首先,我們將獲得帶有請求的查詢參數的搜索項。
const searchTerm = req.query.search;
然後,我們嘗試通過傳遞搜索項從緩存中檢索請求的數據,我們將搜索項用作在緩存中存儲數據時的鍵。由於Redis包不支持承諾,我們必須通過一個回調來處理檢索到的數據。
client.get(searchTerm, async (err, jobs) => {
if (err) throw err;
});
如果Redis返回的值不是null,這意味著相關數據存在於緩存中,所以很容易在響應中返回該數據。只要確保將字符串轉換回JSON即可。
if (jobs) {
res.status(200).send({
jobs: JSON.parse(jobs),
message: "data retrieved from the cache"
});
}
如果返回值為null,我們必須向外部API發送請求以檢索相關數據。
else {
const jobs = await axios.get(`https://jobs.github.com/positions.json?search=${searchTerm}`);
client.setex(searchTerm, 600, JSON.stringify(jobs.data));
res.status(200).send({
jobs: jobs.data,
message: "cache miss"
});
}
當我們從API獲取數據時,在發送回之前,我們將其存儲在Redis中,這樣下次同樣的請求被發送到節點伺服器時,它就可以用存儲在緩存中的數據來響應,而不是從API中請求數據。
注意我們是如何使用setex函數在緩存中存儲數據的。具體地使用setex函數而不是常規的set函數,我們可以為存儲的鍵值對設置過期時間。因為我們為過期時間設置了一個值,所以當過期時,Redis會自動從緩存中刪除該鍵值對。
完整原始碼
const express = require("express");
const axios = require("axios");
const redis = require("redis");
const app = express();
const redisPort = 6379
const client = redis.createClient(redisPort);
client.on("error", (err) => {
console.log(err);
})
app.get("/jobs", (req, res) => {
const searchTerm = req.query.search;
try {
client.get(searchTerm, async (err, jobs) => {
if (err) throw err;
if (jobs) {
res.status(200).send({
jobs: JSON.parse(jobs),
message: "data retrieved from the cache"
});
}
else {
const jobs = await axios.get(`https://jobs.github.com/positions.json?search=${searchTerm}`);
client.setex(searchTerm, 600, JSON.stringify(jobs.data));
res.status(200).send({
jobs: jobs.data,
message: "cache miss"
});
}
});
} catch(err) {
res.status(500).send({message: err.message});
}
});
app.listen(process.env.PORT || 3000, () => {
console.log("Node server started");
});
就是這樣。我們已經為應用程式創建了一個簡單的緩存。這並不難,對吧?
真相時刻:時間比較
我們將看到緩存的使用如何影響我們的應用程式的性能。我使用了Postman來發送請求到伺服器並測量請求完成時間。
第一次向伺服器發送帶有新搜索詞的請求時,應用程式需要更長的響應時間(超過7秒),因為它必須從外部API獲取數據。第二次發出相同請求時,伺服器的響應速度更快,因為結果已經存在於緩存中。
請求在10毫秒內完成。與我們之前看到的沒有緩存的應用程式相比,這是一個巨大的性能提升。
總結
在本教程中,我們給你一個快速介紹Redis和創建一個簡單的緩存與Node.js應用。現在你可以使用Redis來緩存你的應用程式中經常被查詢的數據來獲得一個相當大的性能提升。
你也可以看看如何在其他用例中利用最好的功能。