feat:添加Redis缓存服务

- 实现Redis服务接口和抽象层
- 提供真实Redis服务实现 (RealRedisService)
- 提供文件模拟Redis服务 (FileRedisService) 用于开发测试
- 支持基本的Redis操作:get、set、del、exists、ttl
- 添加Redis模块配置和依赖注入
This commit is contained in:
moyin
2025-12-17 20:20:18 +08:00
parent e58cc57769
commit de30649826
5 changed files with 618 additions and 0 deletions

200
src/core/redis/README.md Normal file
View File

@@ -0,0 +1,200 @@
# Redis 适配器
这个Redis适配器提供了一个统一的接口可以在本地开发环境使用文件存储模拟Redis在生产环境使用真实的Redis服务。
## 功能特性
- 🔄 **自动切换**: 根据环境变量自动选择文件存储或真实Redis
- 📁 **文件存储**: 本地开发时使用JSON文件模拟Redis功能
-**真实Redis**: 生产环境连接真实Redis服务器
- 🕒 **过期支持**: 完整支持TTL和自动过期清理
- 🔒 **类型安全**: 使用TypeScript接口确保类型安全
- 📊 **日志记录**: 详细的操作日志和错误处理
## 环境配置
### 开发环境 (.env)
```bash
# 使用文件模拟Redis
USE_FILE_REDIS=true
NODE_ENV=development
# Redis配置文件模式下不会使用
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD=
REDIS_DB=0
```
### 生产环境 (.env.production)
```bash
# 使用真实Redis
USE_FILE_REDIS=false
NODE_ENV=production
# Redis服务器配置
REDIS_HOST=your_redis_host
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password
REDIS_DB=0
```
## 使用方法
### 1. 在模块中导入
```typescript
import { Module } from '@nestjs/common';
import { RedisModule } from './core/redis/redis.module';
@Module({
imports: [RedisModule],
// ...
})
export class YourModule {}
```
### 2. 在服务中注入
```typescript
import { Injectable, Inject } from '@nestjs/common';
import { IRedisService } from './core/redis/redis.interface';
@Injectable()
export class YourService {
constructor(
@Inject('REDIS_SERVICE') private readonly redis: IRedisService,
) {}
async example() {
// 设置键值对30秒后过期
await this.redis.set('user:123', 'user_data', 30);
// 获取值
const value = await this.redis.get('user:123');
// 检查是否存在
const exists = await this.redis.exists('user:123');
// 删除键
await this.redis.del('user:123');
}
}
```
## API 接口
### set(key, value, ttl?)
设置键值对,可选过期时间
```typescript
await redis.set('key', 'value', 60); // 60秒后过期
await redis.set('key', 'value'); // 永不过期
```
### get(key)
获取值不存在或已过期返回null
```typescript
const value = await redis.get('key');
```
### del(key)
删除键,返回是否删除成功
```typescript
const deleted = await redis.del('key');
```
### exists(key)
检查键是否存在
```typescript
const exists = await redis.exists('key');
```
### expire(key, ttl)
设置键的过期时间
```typescript
await redis.expire('key', 300); // 5分钟后过期
```
### ttl(key)
获取键的剩余过期时间
```typescript
const remaining = await redis.ttl('key');
// -1: 永不过期
// -2: 键不存在
// >0: 剩余秒数
```
### flushall()
清空所有数据
```typescript
await redis.flushall();
```
## 文件存储详情
### 数据存储位置
- 数据目录: `./redis-data/`
- 数据文件: `./redis-data/redis.json`
### 过期清理
- 自动清理: 每分钟检查并清理过期键
- 访问时清理: 获取数据时自动检查过期状态
- 持久化: 数据变更时自动保存到文件
### 数据格式
```json
{
"key1": {
"value": "data",
"expireAt": 1640995200000
},
"key2": {
"value": "permanent_data"
}
}
```
## 切换模式
### 自动切换规则
1. `NODE_ENV=development``USE_FILE_REDIS=true` → 文件存储
2. `USE_FILE_REDIS=false` → 真实Redis
3. 生产环境默认使用真实Redis
### 手动切换
修改环境变量后重启应用即可切换模式:
```bash
# 切换到文件模式
USE_FILE_REDIS=true
# 切换到Redis模式
USE_FILE_REDIS=false
```
## 测试
运行Redis适配器测试
```bash
npm run build
node test-redis-adapter.js
```
## 注意事项
1. **数据迁移**: 文件存储和Redis之间的数据不会自动同步
2. **性能**: 文件存储适合开发测试生产环境建议使用Redis
3. **并发**: 文件存储不支持高并发,仅适用于单进程开发环境
4. **备份**: 生产环境请确保Redis数据的备份和高可用配置
## 故障排除
### 文件权限错误
确保应用有权限在项目目录创建 `redis-data` 文件夹
### Redis连接失败
检查Redis服务器配置和网络连接
```bash
# 测试Redis连接
redis-cli -h your_host -p 6379 ping
```
### 模块导入错误
确保在使用Redis服务的模块中正确导入了RedisModule