Nest 中使用 Redis
本文重点解释 ioredis 的安装与使用,以及如何在 Nest 中使用 ioredis。
ioredis
我这里使用的是 yml 配置文件
安装 ioredis 类库
ts
pnpm install ioredis --save创建一个全局模块 redis
- 代码
ts
nest g resource redis修改这个模块
(1) 删除控制器 redis.controller.ts
(2) 修改 redis.module.ts
ts
// redis.module.ts
import { Module, Global } from "@nestjs/common";
import { ConfigService } from "@nestjs/config";
import { Redis } from "ioredis";
import { RedisService } from "./redis.service.js";
@Global()
@Module({
providers: [
{
provide: "REDIS_CLIENT",
useFactory: (configService: ConfigService) => {
const redis = new Redis({
// Redis 服务器主机地址,默认 localhost
host: configService.get<string>("REDIS_HOST", "localhost"),
// Redis 服务器端口,默认 6379
port: configService.get<number>("REDIS_PORT", 6379),
// Redis 认证密码
password: configService.get<string>("REDIS_PASSWORD"),
// 使用的数据库索引,默认 0
db: configService.get<number>("REDIS_DB", 0),
// 使用 IPv4 协议
family: 4,
// 延迟连接:调用 connect() 时才真正建立连接,避免启动时阻塞
lazyConnect: true,
// 连接超时时间:10 秒
connectTimeout: 10000,
// 重试策略:每次重试间隔递增 1 秒,最多 10 秒
retryStrategy: (times) => Math.min(times * 1000, 10000),
// 单条命令最大重试次数
maxRetriesPerRequest: 3,
// key 前缀,用于命名空间隔离,防止 key 冲突
keyPrefix: configService.get<string>("REDIS_PREFIX", ""),
});
redis.on("connect", () => console.log("[Redis] connecting..."));
redis.on("ready", () => console.log("[Redis] ready"));
redis.on("error", (err) => console.error("[Redis] error:", err));
redis.on("close", () => console.warn("[Redis] connection closed"));
redis.on("reconnecting", () => console.log("[Redis] reconnecting..."));
return redis;
},
inject: [ConfigService],
},
RedisService,
],
exports: [RedisService],
})
export class RedisModule {}- (3) 修改 redis.service.ts(env 配置)
ts
import { Inject, Injectable, OnModuleDestroy } from "@nestjs/common";
import { Redis } from "ioredis";
import { ConfigService } from "@nestjs/config";
@Injectable()
export class RedisService implements OnModuleDestroy {
constructor(
@Inject("REDIS_CLIENT") private readonly redis: Redis,
private readonly configServiceAll: ConfigService,
) {}
async onModuleDestroy() {
await this.redis.quit();
}
// Redis获取所有的keys(使用 SCAN 避免阻塞)
async getAllKeys(pattern: string = "*"): Promise<string[]> {
const keys: string[] = [];
let cursor = "0";
do {
const [nextCursor, foundKeys] = await this.redis.scan(
cursor,
"MATCH",
pattern,
"COUNT",
100,
);
cursor = nextCursor;
keys.push(...foundKeys);
} while (cursor !== "0");
return keys;
}
// Redis 获取单个key的值
async get(key: string): Promise<string | null> {
return await this.redis.get(key);
}
// 删除
async delkey(key: string): Promise<number> {
return await this.redis.del(key);
}
// 字符串方法 data 里面 有key ,value,ttl(可选)
async setstr(data: { key: string; value: string }, ttl?: number) {
const expiration =
ttl || this.configServiceAll.get<number>("REDIS_TTL", 3600);
await this.redis.set(data.key, data.value, "EX", expiration);
return { [data.key]: data.value };
}
// -------------哈希只能一级。要是嵌套太多 就转成字符串 --------------------
async sethash(key: string, data: Record<string, any>, ttl?: number) {
const pipeline = this.redis.pipeline();
for (const [field, value] of Object.entries(data)) {
pipeline.hset(key, field, value);
}
const expiration =
ttl || this.configServiceAll.get<number>("REDIS_TTL", 3600);
pipeline.expire(key, expiration);
await pipeline.exec();
return this.gethash(key);
}
async gethash(key: string): Promise<Record<string, string>> {
return await this.redis.hgetall(key);
}
// ---------------- 列表设置 ------------
async setlist(key: string, data: any[], ttl?: number) {
const pipeline = this.redis.pipeline();
for (const item of data) {
pipeline.rpush(key, item);
}
const expiration =
ttl || this.configServiceAll.get<number>("REDIS_TTL", 3600);
pipeline.expire(key, expiration);
await pipeline.exec();
return this.getlist(key);
}
//-------------列表获取----------
async getlist(key: string): Promise<string[]> {
return await this.redis.lrange(key, 0, -1);
}
}使用
控制器
ts
import { Controller, Post, Body } from "@nestjs/common";
import { UserService } from "./user.service";
@Controller("user")
export class UserController {
constructor(private readonly userService: UserService) {}
// 查询所有的key
@Post("getallkeys")
async getallkeys() {
const result = await this.userService.getAllKeys();
console.log(result);
return {
data: result,
};
}
// 查看匹配的keys
@Post("getcheckkeys")
async getcheckkeys(@Body() body: any) {
const params = body.value;
console.log(params);
const result = await this.userService.getcheckkeys(params);
console.log(result);
return {
data: result,
};
}
// 删除指定的key
@Post("delkey")
async delkey(@Body() body: any) {
const params = body.value;
console.log(params);
const result = await this.userService.delkey(params);
let message = "";
if (result == 1) {
message = "删除成功";
}
return {
data: {
message,
},
};
}
// ------------- 字符串-------------------
// 设置字符串
@Post("setstr")
async setstr(@Body() body: any) {
const value = body.value;
const key = body.key;
const result = await this.userService.setstr({ key, value });
console.log(result);
return {
data: result,
};
}
// 获取字符串
@Post("getstr")
async getstr(@Body() body: any) {
const key = body.key;
const result = await this.userService.getstr(key);
console.log(result);
return {
data: result,
};
}
// -------------对象Hash开始---------------
@Post("sethash")
async sethash(@Body() body: any) {
const hashresult = { key: "hash1", value: { ...body } };
const result = await this.userService.sethash(
hashresult.key,
hashresult.value,
);
console.log(result);
return {
data: result,
};
}
// --------获取hash------
@Post("gethash")
async gethash(@Body() body: any) {
const key = body.key;
const result = await this.userService.getallhash(key);
console.log(result);
return {
data: result,
};
}
// -------------列表---------------
@Post("setlist")
async setlist(@Body() body: any) {
console.log(body);
const listresult = { key: "list1", value: [...body.list1] };
const result = await this.userService.setlist(
listresult.key,
listresult.value,
);
console.log(result);
return {
data: result,
};
}
// --------列表获取------------
@Post("getlist")
async getlist(@Body() body: any) {
const key = body.key;
const result = await this.userService.getlist(key);
console.log(result);
return {
data: result,
};
}
}services
ts
import { Inject, Injectable } from "@nestjs/common";
import { RedisService } from "../redis/redis.service";
import { ConfigService } from "@nestjs/config";
import { JwtServiceAll } from "../jwt/jwt.service";
// 数据库
import { PrismadbService } from "../prisma/prisma.service";
@Injectable()
export class UserService {
// 注入配置文件
@Inject()
private readonly configService: ConfigService;
// 注入Redis
@Inject()
private readonly redisService: RedisService;
// 注入jwt
@Inject()
private readonly jwtService: JwtServiceAll;
// 注入数据库
@Inject()
private readonly prismadbService: PrismadbService;
// 获取所有的keys
async getAllKeys() {
const result = await this.redisService.getAllKeys();
return result;
}
// 获取所有匹配的keys
async getcheckkeys(data: string) {
const result = await this.redisService.getAllKeys(data);
return result;
}
// 删除指定的key
async delkey(data: string) {
const result = await this.redisService.delkey(data);
return result;
}
// 字符串方法设置
async setstr(data: Object) {
const result: any = await this.redisService.setstr(data);
return result;
}
// 字符串方法获取
async getstr(data: string) {
const result: any = await this.redisService.getstr(data);
return result;
}
/*------------------设置hash------------------------*/
async sethash(key: string, data: Object) {
const result: any = await this.redisService.sethash(key, data);
return result;
}
// 获取所有的hash
async getallhash(key: string) {
const result: any = await this.redisService.gethash(key);
return result;
}
// ---------列表-------------------
async setlist(key: string, data: any[]) {
const result: any = await this.redisService.setlist(key, data);
return result;
}
async getlist(key: string) {
const result: any = await this.redisService.getlist(key);
return result;
}
}