说实话,这篇文章可以被列进我最不想写的文章TOP3,因为写这种在XX中使用XX的人实在太多了,如果你想知道如何在XX中使用XX,不用翻看自己的文章,直接网络上搜索,多得是。但我为什么最终还是决定把这个问题记录下来,因为NestJS这玩意实在太扯淡了。
我曾经三次参考网上教程将Redis引入NestJS,三次都花了很长时间,其中有很大一部分原因不知道是版本问题还是其他别的什么问题,他们写的方法,我照着写会报错,我可去他的吧。而且如果有耐心搜过这玩意的同学会发现,古今中外有不少人试图用不同的方法不同的npm包去实现这件事并留下了各种一样或不一样的记录,stack overflow也有很多在尝试其他人方法时遇到我一样报错人的解决办法,总而言之,他们的方法太不靠谱,成功率也太低了。
关于使用Redis我曾经有两种构想,一种是将原本的Cache源替换,兼容老的cache相关方法,另一种是引入新的redis方法,新老互不影响。前几次我都是采用第一种方案,碰了不少壁,虽然成功了,但代价巨大,这一次我决定使用第二种。不过如果想用第一种方案的同学也别着急退出,也许这篇文章多少会对你有点启发。
那就正式开始了。
一、别人怎么说的
熟悉我的人都知道,我想知道一个功能怎么做,第一反应是去翻官方文档,关于如何引入Redis,官方有两种方式,一种是直接替换,一种是使用微服务。
直接替换的情况下,官方推荐的是cache-manager-redis-store
,也怪我没看清楚,文档下面用黄字标注了,这个包只适用于 3.xx版本,而我们公司的Redis买的是 7.xx 版本
不过好在引入的时候也报错了,类型不匹配
至于微服务版本就不用说了,不太会考虑这种引入方式
既然官方文档行不通,我便开始寻找一些路人文章,这里我按日期找了一位看上去还比较靠谱的大哥
但是直接在第一步下载依赖就给我卡住了
@nestjs/redis
包在npm仓库根本找不到,当然,我也尝试过将他下面使用到的一些包直接找到对应依赖下载,依然跑不通,感兴趣的同学可以进到 原文 自行体验。
二、比较可靠的方案
cache-manager-ioredis
包是可以直接引用的,在注册缓存时可以将Redis引入进去实现前面提到的第一种构想。
import * as redisStore from 'cache-manager-ioredis';
CacheModule.register({
store: redisStore,
host: 'redis地址',
port: 6379,
password: 'YImu654321',
isGlobal: true,
db: 0,
ttl: 3600 * 24
}),
但是这里并不是想讲这种方法,所以一笔带过。
在更早之前,我找到过一个类似包,叫cache-manager-redis-yet
,是cache-manager-redis-store
引入报错时从stack overflow的一篇解答里推荐的,这次我想重新试试这个包好不好用,但发现npm中找不到了
通过地址栏进去之后会发现它被弃用了,最后一次推送是17天前
要知道, cache-manager-ioredis
的上次推送时间是4年前
这就让我对弃用信息里提到的keyv产生了兴趣,毕竟它的上次推送时间是3天前,周下载量是三千两百万
三、keyv
keyv的使用方式非常简单,详情可以参考 官方npm文档
引入:
npm install --save keyv
npm install --save @keyv/redis
使用:
import Keyv from 'keyv';
import KeyvRedis from '@keyv/redis';
const keyvRedis = new KeyvRedis('redis://user:pass@localhost:6379');
const keyv = new Keyv({ store: keyvRedis });
await keyv.set('foo', 'expires in 1 second', 1000); // true
await keyv.set('foo', 'never expires'); // true
await keyv.get('foo'); // 'never expires'
await keyv.delete('foo'); // true
await keyv.clear(); // undefined
但是,由于众所周知的原因,我们不可能每次需要使用redis的时候都去重新连接一次,所以我们一般会用注册的方式引入
import { Module, Global } from '@nestjs/common';
import Keyv from 'keyv';
import KeyvRedis from '@keyv/redis';
@Global() // 可选:如果你希望这个模块在整个应用中可用
@Module({
providers: [
{
provide: 'CACHE',
useFactory: () => {
const keyv = new Keyv({ store: new KeyvRedis("redis://:密码@redis地址:6379/0") }); // 可以根据你的配置选择存储
return keyv;
},
},
],
exports: ['CACHE'],
})
export class RedisModule {}
其中6379
对应的是redis的端口号,/0
对应的是redis的字典库,redis默认有16个库,分别是db0~db15,不同db之间数据不共通,可以用于区分环境,但需要注意的是集群redis可能只有db0。
引入方式也很简单,这里就不贴代码了,用过NestJS的小伙伴对这种引用应该已经很熟悉了,注意这里的 CACHE
要和上面填写的的provide和exports相对应。
如果想设置过期时间,可以在set时添加:
await this.cacheServer.set("test", "测试存放内容", 60 * 1000);
对应的时间单位是毫秒。
添加完成后可以在redis客户端找到相应的缓存数据:
四、拓展
如果你有在关注cache-manage
这个包的话,你会发现,它的 npm文档 近期也有更新,不难看出keyv将会是后续nestjs cache使用上比较主流的方式,由于我的项目目前使用的版本号有点老旧,更新稍微有点困难,就不做尝试了,有兴趣的小伙伴可以安装新版本体验一下。