JavaScript中的缓存:Redis、Memcached及内置解决方案

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

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

开始课程

JavaScript中的缓存:Redis、Memcached及内置解决方案:从入门到精通



在现代Node.js Web开发中,应用程序性能直接取决于数据访问速度。每次对数据库、外部API或文件系统的请求都会产生延迟,随着负载增加,这种延迟会不断累积。缓存是一种将频繁请求的数据临时存储在快速存储中的策略,能够将响应时间缩短10到100倍。在本文中,我们将探讨JavaScript中的三种缓存方法:内置解决方案(Map、WeakMap、node-cache模块)、分布式系统Redis和Memcached,以及它们的组合使用。



为什么Node.js需要缓存?

缓存的主要目的是减轻慢速资源(数据库、磁盘、外部服务)的负载,并加快向用户提供数据的速度。在典型的Node.js Web应用中,缓存可以存储:

  • 复杂数据库查询的结果(聚合、JOIN操作)。
  • 外部API的响应(天气、汇率、地理数据)。
  • 用户会话和身份验证令牌。
  • HTML片段或整个页面(SSR缓存)。
  • 配置文件和模板。

没有缓存,每次重复访问相同的数据都会导致重复工作。有了缓存,数据可以在微秒内从内存中获取。



JavaScript中的内置缓存解决方案

对于简单场景或单线程应用,可以使用JavaScript的原生数据结构。它们不需要安装外部包,但在容量和生命周期方面有限制。



1. Map和WeakMap

Map对象是一个键值对集合,非常适合在单个进程内实现缓存。以下是带有TTL(生存时间)的简单缓存示例:

class SimpleCache {  constructor(ttl = 60000) {    this.cache = new Map();    this.ttl = ttl;  }

set(key, value) { this.cache.set(key, { value, expiry: Date.now() + this.ttl }); }

get(key) { const item = this.cache.get(key); if (!item) return null; if (Date.now() > item.expiry) { this.cache.delete(key); return null; } return item.value; }

has(key) { return this.get(key) !== null; }}

// 使用示例const cache = new SimpleCache(5000); // TTL 5秒cache.set('user:123', { name: '伊万' });console.log(cache.get('user:123')); // { name: '伊万' }

WeakMap的不同之处在于其键只能是对象,并且如果键对象不再被引用,垃圾回收器可以删除条目。这对于缓存DOM元素或临时对象非常方便。



2. node-cache模块

对于生产环境,最好使用现成的node-cache库。它支持TTL、自动清理,并且比自建方案运行更快:

const NodeCache = require('node-cache');const myCache = new NodeCache({ stdTTL: 100, checkperiod: 120 });

// 写入myCache.set('key', { data: 'value' });

// 读取const value = myCache.get('key');if (value === undefined) { // 缓存未命中——需要从数据库获取数据}

// 删除myCache.del('key');

内置解决方案适用于单体应用或单实例微服务。然而,当扩展到多个进程或服务器时,数据会变得不一致——这时就需要分布式缓存。



Redis:强大的内存数据存储

Redis是一个高性能的内存数据存储,支持字符串、哈希、列表、集合等多种数据结构。对于Node.js,可以使用redis或ioredis包。Redis非常适合缓存,原因如下:

  • 支持键级别的TTL(EXPIRE命令)。
  • 原子操作(INC

博客

书籍推荐