在Web开发中,缓存是提升系统性能最直接有效的手段之一。ThinkJS作为一款基于Node.js的企业级服务端框架,内置了一套灵活的缓存机制,支持内存、文件、Redis等多种缓存适配器。但不少开发者在使用过程中,对缓存的配置方式、调用方法以及常见报错的处理并不熟悉。本文将从零开始,把ThinkJS Cache缓存的知识点一次性讲透,并汇总实际开发中最常见的几个问题。

一、ThinkJS缓存的基本概念
缓存的本质是把一些计算成本高或访问频繁的数据临时存储起来,下次需要时直接读取,避免重复计算或反复请求数据库。ThinkJS封装了一套统一的缓存接口,无论底层使用的是内存、文件还是Redis,对上层代码来说调用方式基本一致。
ThinkJS内置了多种缓存类型。memory是内存缓存,数据存在进程内存里,速度最快,但服务重启后数据丢失,且不适合多进程共享场景;file是文件缓存,数据持久化到磁盘文件中,适合单机部署的项目;redis则是通过Redis服务存储缓存,支持分布式部署,是多实例、多进程环境下最常用的方案。
除了这三种,ThinkJS还支持memcache等类型,同时允许开发者自定义adapter扩展自己的缓存后端,比如接入公司内部的缓存集群。理解每种缓存类型的适用场景,是用好缓存的第一步。
二、缓存配置方法详解
ThinkJS的缓存配置位于项目的config目录下,通常写在src/config/config.js(旧版本可能是src/common/config/config.js)中。核心配置项是cache对象,示例如下:
配置文件类型时,type设置为file,可以通过cache_path指定缓存文件存放目录,file_timeout_factor是文件缓存的时间放大系数。配置Redis时,type设置为redis,需要填写host、port,如果有密码则加上password字段。需要注意的是,Redis配置的key_prefix可以避免多个项目共用同一个Redis实例时发生键名冲突,建议在配置中显式指定。
ThinkJS还支持按类型区分配置,例如为不同模块配置不同的缓存后端。如果项目中有部分数据对实时性要求极低(比如商品分类树),可以单独给它配置一个超长过期时间的Redis实例,而热点计数类数据则用内存缓存,这样能充分利用各类缓存的优势。
三、在代码中使用缓存API
ThinkJS提供了两种常用的缓存调用方式。第一种是直接使用缓存API:think.cache('key')用于读取缓存,think.cache('key', value)用于写入缓存,think.cache('key', null)用于删除缓存。写入时还可以传入第三个参数指定过期时间(单位为毫秒),例如think.cache('userInfo', data, 3600 * 1000)表示一小时后自动失效。
第二种是在模型或控制器中使用this.cache方法,用法与全局API一致。例如在控制器中:
this.cache('siteConfig').then(data => { if (think.isEmpty(data)) { return getFromDb().then(res => this.cache('siteConfig', res, 60000)); } return data; });
这种先查缓存、缓存未命中再查数据库、最后回写缓存的模式,是业务开发中最经典的用法。建议把这类逻辑封装成独立函数,避免在多个地方重复编写,也方便后期统一调整过期策略。
四、常见问题与解决方案汇总
1. 缓存写入后读取不到
最常见的原因是缓存类型配置成了memory且项目开启了cluster多进程模式。内存缓存是进程隔离的,A进程写入的数据B进程读不到。解决办法是改用Redis或文件缓存。另一个原因是键名不一致,比如写入时用了前缀而读取时没加前缀,建议统一封装key的生成规则。
2. Redis连接失败报错
遇到Redis连接异常时,先检查host和port是否正确,再用redis-cli手动连一次确认网络通畅。如果Redis设置了密码但配置里没写password字段,会一直连接失败。另外,如果线上使用了云Redis,注意检查白名单是否放行了服务器IP。
3. 缓存对象序列化报错
文件缓存和Redis缓存都会对数据进行序列化,如果缓存的对象中包含函数、循环引用或Buffer等无法正常序列化的内容,就会报错。解决办法是只缓存纯JSON数据,入库前把非序列化字段剔除掉。
4. 缓存过期时间不生效
检查是否把毫秒写成了秒。ThinkJS缓存超时单位是毫秒,如果传了3600以为是一小时,实际只有3.6秒。另外文件缓存的过期判断依赖访问触发,长时间无人访问的缓存文件可能不会立即清理,这是正常现象。
5. 缓存穿透导致数据库压力过大
当大量请求查询一个不存在的key时,缓存永远不会命中,请求全部打到数据库。可以在缓存未命中且数据库也查不到时,写入一个空值并设置较短的过期时间(比如60秒),这样后续请求会命中这个空值缓存,有效保护数据库。
五、使用缓存的最佳实践
第一,key的命名要规范,建议采用“项目名:模块:业务名:id”的格式,例如shop:goods:detail:10086,既便于排查问题,也避免键名冲突。第二,合理设置过期时间,原则上数据和业务容忍度匹配即可,不要为了省事设置永久缓存,否则数据更新后会出现长期不一致。第三,更新数据库时要及时处理缓存,常用策略是先更新库再删除缓存,下次请求时自然回源重建。
第四,重要的缓存操作要加上错误处理。Redis偶尔抖动时,缓存调用失败不应该影响主业务流程,可以用try-catch包裹并把降级逻辑写成查库,保证服务可用性。第五,上线前务必监控缓存的命中率,命中率长期偏低说明缓存策略有问题,需要及时调整key设计或过期时间。
总结一下,ThinkJS的缓存体系并不复杂,关键是选对缓存类型、规范key命名、处理好缓存与数据库的一致性。把本文的配置方法和问题排查思路掌握后,日常开发中绝大多数缓存相关的需求都能轻松应对。
ThinkJS缓存ThinkJS Cache缓存配置修改时间:2026-09-16 05:44:37