使用 Redis 与 NestJS 10 的正确姿势

前言

在开发过程中,缓存是提升性能的利器,而 Redis 则是缓存界的明星选手。然而,随着技术栈的更新,NestJS 与 Redis 的集成方式也在不断变化。最近,我在项目中尝试将 Redis 集成到 NestJS 中,结果踩了不少坑,尤其是在 cache-manager 的版本变迁和 Keyv 的引入上。于是,我决定写下这篇博客,既是技术总结,也是踩坑记录,希望能帮到同样在坑里挣扎的你。


踩坑背景:cache-manager 的版本变迁

在过去,NestJS 使用 cache-manager 来管理缓存,而 Redis 的支持通常通过 cache-manager-redis-yetcache-manager-ioredis-yet 实现。然而,随着 cache-manager 升级到 v6,这些插件已经被抛弃,取而代之的是 Keyv,一个更现代化的存储适配器。

于是,问题来了:如果你还在用老版本的 cache-manager,你可能会遇到诸如 cacheManager.caching is not a function 这样的报错。而如果你升级到了 v6,却还在用老的 Redis 插件,那你会发现它们根本不兼容。

所以,正确的姿势是:拥抱变化,使用 Keyv@keyv/redis 来集成 Redis


正确姿势:NestJS + Redis + Keyv

以下是正确的 Redis 集成方式,分步骤为你讲解。


1. 创建 NestJS 项目

首先,创建一个新的 NestJS 项目。如果你已经有项目,可以跳过这一步。

Loading...

2. 安装必要的依赖

安装 Keyv 和 Redis 的适配器 @keyv/redis,以及 cacheable(一个强大的缓存管理库)。

Loading...

3. 创建缓存模块

接下来,我们创建一个专门的模块来管理缓存逻辑。

Loading...

然后,在 cache.module.ts 中配置 Redis 缓存:

Loading...

4. 创建缓存服务

为了更方便地操作缓存,我们创建一个服务来封装缓存逻辑。

Loading...

cache.service.ts 中实现缓存操作方法:

Loading...

5. 在控制器中使用缓存

最后,我们在控制器中使用缓存服务来实现数据缓存。

Loading...

sample.controller.ts 中实现以下逻辑:

Loading...

6. 测试缓存功能

启动应用程序并访问 /sample 路由:

Loading...
  • 第一次访问时,数据会从外部 API 模拟获取,并缓存 1 分钟。
  • 后续访问时,数据会直接从缓存中获取,直到缓存过期。

踩坑记录

在实现上述功能的过程中,我踩了以下几个坑:

  1. cache-manager 的版本问题

    • 如果你用的是 cache-manager v4,那么 TTL 是以秒为单位的。
    • 如果你用的是 cache-manager v5 或 v6,那么 TTL 是以毫秒为单位的。
    • 解决方案:直接使用 Keyv@keyv/redis,避免版本兼容问题。
  2. 弃用的 Redis 插件

    • cache-manager-redis-yetcache-manager-ioredis-yet 已经被废弃。
    • 解决方案:使用 @keyv/redis 作为 Redis 的存储适配器。
  3. 多层缓存的实现

    • 如果需要多层缓存(如内存缓存 + Redis 缓存),可以使用 Cacheable 提供的多层存储功能。

总结

通过这次踩坑,我学到了以下几点:

  1. 拥抱变化:技术栈的更新不可避免,与其抱怨,不如快速适应。
  2. 阅读文档:很多问题其实文档里都写了,只是我们没仔细看。
  3. 记录踩坑:每次踩坑都是一次学习的机会,记录下来不仅能帮助自己,也能帮助他人。

希望这篇博客能帮你少踩坑,快速上手 NestJS 与 Redis 的集成。如果你也有类似的踩坑经历,欢迎在评论区分享!