发布于 2026-01-06 7 阅读
0

Node.js 高级主题:缓存。DEV 全球项目展示挑战赛,由 Mux 主办:展示你的项目!

Node.js 高级主题:缓存。

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

使用 Redis 缓存频繁获取的数据,提高服务器性能。

介绍:

Redis 是一个内存数据库,它以键值对格式存储数据,由于数据存储在内存中,因此速度非常快。

Redis 提供诸如字符串、哈希表、列表、集合、有序集合等数据结构。

Redis 是一个开源(BSD 许可)的内存数据结构存储系统,可用作数据库、缓存、消息代理和流式处理引擎。Redis 提供多种数据结构,例如字符串哈希表列表集合、支持范围查询的有序集合、位图HyperLogLog地理空间索引。Redis 内置了数据复制Lua 脚本LRU 淘汰机制事务以及不同级别的磁盘持久化,并通过Redis Sentinel提供高可用性,并通过Redis Cluster实现自动分区。redi.io


案例用途:

为什么应该在服务器端实现缓存层,以及它将如何提高应用程序的性能。

  • 定期缓存
    获取频率过高的数据是一种很好的做法,这样可以避免用户等待太久才能获取基本数据。


  • 通过使用缓存来减少数据库查询执行次数,不仅可以降低数据库查询次数,还能避免因重复查询返回相同结果而导致数据库不堪重负。
    此外,如果您将应用程序托管在费用昂贵的托管服务商处,还能节省宝贵的带宽。

  • 提升应用性能
    缓存不仅可以提升数据库性能并保护数据库,还能提升整体服务器-客户端性能。
    为了更好地理解这一点,假设你的服务器有一个名为 `getArticle` 的路由,每个发送到该路由的请求大约需要半秒(约 500 毫秒)才能获得响应。使用缓存后,第一个请求可能需要半秒或更长时间,但之后的每个请求只需大约 20 毫秒即可完成!是不是很神奇?!
    我将使用我自己的应用来验证这一点。


启用缓存 vs. 禁用缓存:

我在服务器上做了一个简单的基准测试(使用单个 API 来查看在不使用缓存的情况下完成请求需要多长时间,然后使用缓存重新测试同一个 API 以查看性能提升)。

不使用缓存

上图显示,我的服务器完成请求花费了超过一秒的时间,当然,每次我发出请求时,所需时间都大致相同!

下图是我在服务器 API 中引入缓存机制后的效果,您可以自行查看时间上的变化(我没有更改请求中的任何内容)。

引入缓存

接下来完成相同请求所需的时间已缩短至约 10 毫升,这是一个显著的改进!

希望现在您对在自己的项目中应用这项技术充满热情。


安装:

在您的机器上安装Redis

在 Linux 系统中,您可以通过在终端输入命令来安装它。

sudo apt-get -y install redis
Enter fullscreen mode Exit fullscreen mode

在 macOS 系统中,在终端中输入以下命令

brew install redis
Enter fullscreen mode Exit fullscreen mode

在 Windows 系统中,由于 Redis 并未得到 Windows 官方支持,因此在 Windows 系统上安装 Redis 会比较困难。

Redis 官方不支持 Windows 系统。但是,您可以按照以下说明在 Windows 上安装 Redis 以进行开发。
要在 Windows 上安装 Redis,您首先需要启用 Windows 子系统 Linux 版 ( WSL2
)。WSL2 允许您在 Windows 上原生运行 Linux 二进制文件。要使此方法生效,您需要运行 Windows 10 版本 2004 或更高版本,或者 Windows 11。

https://redis.io/docs/getting-started/installation/install-redis-on-windows/

在您的项目中安装 node-Redis:

node-Redis 是一个现代化的、高性能的 Node.js 客户端。

npm install redis
Enter fullscreen mode Exit fullscreen mode

现在我们已经安装了 Redis 和 node-redis 包,让我们用这些强大的工具做一些简单的工作,然后再尝试在实际示例中使用它们!

Redis快速入门:

// IMPORTANT : before you can establish connection to redis,

// you must start the redis-server

const redis = require('redis');

// create client to communicate redis DB

var client = redis.createClient();

client.connect()

// connect and error events

client.on('error', function (err) {

console.log('Something went wrong ', err)

});

client.on('connect', function () {

console.log('Redis Connected!')

});
Enter fullscreen mode Exit fullscreen mode

连接到 Redis 服务器:

要启动 Redis 服务器,您需要在终端中运行:

redis-server
Enter fullscreen mode Exit fullscreen mode

启动 Redis 服务器

例子:

set() 和 get()

上面我们创建了一个客户端并启动了与 Redis 服务器的连接,现在我们可以使用所有功能了。

// used to put data into redis
client.set("key" , "some value")

// used to get data from redis
client.get("key")
// output = "some value"
Enter fullscreen mode Exit fullscreen mode

现实生活中的例子:

现在最大的问题是,如何利用 set() 和 get() 这些简单的函数来提高服务器性能?

让我们看看我的服务器(一个用于从 MongoDB Atlas 获取报价并发送回服务器的 Express 服务器)。

本次基准测试来自我自己的报价 API(即将发布在 RapidAPI 中),我们将看看请求 1000、3000 和 5000 个数据文档时所需时间的差异,我将重复测试,这次从缓存中获取相同的数据。

未缓存的情况下获取了 1000 个文档

从数据库中检索 1000 个文档耗时近 2 秒。

从缓存中获取的相同 1000 个文档

但是从缓存中获取相同数量的数据仅需 25 毫秒!

未使用缓存获取了 3000 个文档

从数据库中检索 3000 个文档只用了将近 4 秒钟!

从缓存中获取了 3000 个文档

但是从缓存中获取相同数量的数据仅需 45 毫秒!

未使用缓存获取了 5000 个文档

从数据库中检索 5000 个文档仅用了不到 5 秒钟!

从缓存中获取了 5000 个文档

但从缓存中读取,只用了 60 毫秒!

是不是很神奇?


缓存机制:

缓存其实就是在服务器端添加一个额外的层,这个层会拦截数据库即将执行的查询,并检查该查询是否已被缓存。如果已被缓存,则会将缓存的数据作为响应返回,而不会再次向数据库发送查询。如果尚未被缓存,则会将查询发送到数据库执行,并将结果存储在缓存(Redis)中,以供后续请求使用。

感谢 [Linuxiac](https://linuxiac.com/redis-as-cache/)

所以,为了明确我们想要做什么:

  1. 使用上述代码将服务器连接到 Redis。

  2. 我们想要劫持(拦截、中断,随便你怎么称呼)向数据库发送查询的过程,以便判断该查询是否已被缓存。

  3. 如果数据已缓存,则返回缓存数据并结束响应。不要向数据库发送任何内容。

  4. 如果查询未缓存,则发送查询以执行查询并将结果作为响应发送,然后将结果存储在缓存中以供新请求使用。

首先,你需要在项目中创建一个名为 cache.js 的新文件,你可以随意命名,如果项目有 services 目录,就把它放在 services 目录下;如果没有,就把它放在任何位置。

该文件将包含我们的服务器缓存数据和从 Redis 检索数据所需的所有逻辑。

首先,我们需要连接到 Redis 并确保它运行正常。


创建密钥:

为了在 Redis 中存储数据,我们需要为每个查询提供一个唯一且一致的键,以便在收到请求时能够检索到正确的查询。

Redis数据库密钥创建

基本上,对任何数据库的每次查询都有筛选器和选项,用于获取特定的文档或记录。

我们将利用这个东西,把这些过滤器转换成字符串。

 JSON.stringfy({ {title : "story"} , {skip : 10} })
    // our key = "{{"title" : "story" }, {"skip" : 10}}"
    // everytime any client will request the data that can be fetched
    // with this query, the server will repsonse with the cached data

Enter fullscreen mode Exit fullscreen mode

现在我们有了每个需要在数据库中执行的查询的键,接下来我们将在 Redis 中搜索这个键,如果存在,则返回其值而不是执行查询,如果未找到,则在数据库中执行查询,并将查询结果连同其键一起存储在 Redis 中以供后续请求使用,然后将结果发送给用户。

Redis 缓存数据

// this line will add the data fetched from mongoDB to redis
client.set(key, JSON.stringify(result))
// always remember, Redis only store values as a string or numbers
Enter fullscreen mode Exit fullscreen mode

包起来:

首先,你需要为每个查询创建一个唯一且一致的键。

其次,在 Redis 中搜索此键,如果找到,则返回其值作为结果;否则,执行查询并将结果存储在 Redis 中,最后将其发送给用户。


参考:

学习Node.js的最佳课程。

https://www.udemy.com/course/advanced-node-for-developers/?ranMID=39197&ranEAID=SAyYsTvLiGQ&ranSiteID=SAyYsTvLiGQ-EDfB120pgYcJlhkNSEBp4Q&LSNPUBID=SAyYsTvLiGQ&utm_source=aff-campaign&utm_medium=udemyads
如何在 Node.js 中使用 Redis 实现缓存 | DigitalOcean
Redis + Node.js:缓存入门 - RisingStack
使用 Redis 在 Node.js 中实现缓存
使用强大的 Redis 缓存机制加速您的 Node.js 应用程序

用于 Node.js 的 Redis OM


感谢阅读,如果您对 JavaScript 或本系列文章有任何疑问,请随时提出。我非常感谢您的任何反馈,这有助于我改进内容。

您可以在TwitterGithub我的作品集中找到我。

文章来源:https://dev.to/osam1010/advanced-nodejs-topics-caching-46a1