引言:为什么缓存对 TypeScript 应用程序至关重要
现代基于 TypeScript 的 Web 应用程序面临着日益增长的负载和响应速度要求。缓存不仅仅是一个选项,而是任何生产级应用程序的必要条件。没有它,每次对数据库或外部 API 的请求都会变成一项昂贵的操作,使响应时间增加 10 到 100 倍。
在本文中,我们将分析 TypeScript 中三种主要的缓存方法:Redis —— 分布式缓存,Memcached —— 轻量级替代方案,以及内置解决方案(in-memory cache)。您将学习如何选择合适的工具并通过代码示例实现它。
1. 内置缓存:TypeScript 中的 In-Memory Cache
最简单且最快的方法是将数据直接存储在进程的 RAM 中。对于 TypeScript/Node.js,这非常适合单体应用或单实例微服务。
实现一个简单的 in-memory 缓存
让我们创建一个支持 TTL(生存时间)的 SimpleCache 类:
interface CacheEntry<T> {
value: T;
expiresAt: number;
}
class SimpleCache<T> {
private store = new Map<string, CacheEntry<T>>();
private defaultTTL: number; // 以毫秒为单位
constructor(defaultTTL: number = 60000) {
this.defaultTTL = defaultTTL;
}
set(key: string, value: T, ttl?: number): void {
const expiresAt = Date.now() + (ttl ?? this.defaultTTL);
this.store.set(key, { value, expiresAt });
}
get(key: string): T | null {
const entry = this.store.get(key);
if (!entry) return null;
if (Date.now() > entry.expiresAt) {
this.store.delete(key);
return null;
}
return entry.value;
}
has(key: string): boolean {
return this.get(key) !== null;
}
delete(key: string): void {
this.store.delete(key);
}
clear(): void {
this.store.clear();
}
}
// 使用示例
const userCache = new SimpleCache<User>(30000); // TTL 30 秒
userCache.set('user:123', { id: 123, name: 'Anna' });
const cachedUser = userCache.get('user:123');
In-memory 缓存的优缺点
- 优点: 极快速度(纳秒级),无网络延迟,实现简单。
- 缺点: 应用程序重启时数据丢失,受限于单个进程的 RAM 容量,无法在水平扩展时工作。
何时使用: 用于缓存繁重计算的结果、配置、以及很少更改的静态数据。
2. Redis:TypeScript 的分布式缓存
Redis 是最流行的 in-memory data store,用作缓存、消息代理和数据库。对于 TypeScript,我们使用 ioredis 库。
安装和基本配置
npm install ioredis
npm install @types/ioredis -D
创建一个用于操作 Redis 的服务:
import Redis from 'ioredis';
class RedisCacheService {
private client: Redis;
private defaultTTL: number;
constructor(ttlSeconds: number = 3600) {
this.client = new Redis({
host: process.env.REDIS_HOST || 'localhost',
port: Number(process.env.REDIS_PORT) || 6379,
retryStrategy: (times) => Math.min(times * 50, 2000),
});
this.defaultTTL = ttlSeconds;
}
async set<T>(key: string, value: T, ttl?: number): Promise<void> {
const serialized = JSON.stringify(value);
const ttlToUse = ttl ?? this.defaultTTL;
await this.client.setex(key, ttlToUse, serialized);
}
async get<T>(key: string): Promise<T | null> {
const data = await this.client.get(key);
if (!data) return null;
try {
return JSON.parse(data) as T;
} catch {
return null;
}
}
async delete(key: string): Promise<void> {
await this.client.del(key);
}
async clear(): Promise<void> {
await this.client.flushall();
}
}
// 使用示例
const redisCache = new RedisCacheService(1800); // TTL 30 分钟
await redisCache.set('session:456', { userId: 456, role: 'admin' });
const session = await redisCache.get<Session>('session:456');
Redis 的优缺点
- 优点: 支持分布式系统,数据持久化,丰富的数据结构(列表、集合、哈希等),内置 TTL 管理。
- 缺点: 需要单独的服务器/基础设施,存在网络延迟(尽管很小),配置比 in-memory 缓存更复杂。
何时使用: 用于跨多个应用程序实例共享缓存、会话存储、API 响应缓存、以及需要持久化的数据。
```