TypeScript 中的缓存:Redis、Memcached 及内置方案

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程
```html

引言:为什么缓存对 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 响应缓存、以及需要持久化的数据。

```

博客

书籍推荐