跳到主要内容

Node.js 连 Redis 时,key 命名和过期时间最好一起设计

· 阅读需 3 分钟
一介布衣
全栈开发者

2014 年前后,Node.js 配 Redis 是很常见的一套轻量组合。大家一开始都觉得 Redis 上手快,setget 会用就能干活,但真把它放进登录态、验证码、计数器、页面缓存之后,问题很快就来了:key 越堆越多,过期时间各写各的,最后自己都看不懂线上到底存了什么。

我后来慢慢意识到,Redis 不是“先存起来再说”的临时抽屉,尤其在 Node.js 项目里,请求量一上来,key 命名和过期时间如果没有一起设计,后面定位问题会特别慢。

我最早踩过的坏味道

一开始最容易出现三种写法:

  • key 直接拿业务字段名拼,比如 user_12user12code
  • 同一类数据的过期时间完全靠调用方自己决定
  • 没有环境前缀,测试和正式约定全靠人记

这种写法在功能刚上线时感觉没什么,但一周后再看,Redis 里会充满“自己认识、别人不认识,三天后自己也不认识”的键。

我后来固定下来的 key 结构

我更喜欢把 key 当成一层简化后的命名空间:

  • prod:user:123:profile
  • prod:user:123:session
  • prod:post:list:home:v2
  • prod:sms:login:138xxxx:cooldown

这样做的好处不是好看,而是你用 keys prod:user:123:* 或者后面做扫描排查时,能立刻知道一串数据到底属于谁、是做什么的、有没有版本。

对 Node.js 服务来说,最重要的是“调用方越多,命名越不能自由发挥”。宁可前面多写几个冒号,也不要把语义省掉。

过期时间别只看“多久失效”

很多人第一次给 Redis 设置过期时间,只会问一句:“这个 key 放多久?”但线上真正该问的其实是另外三件事:

  • 这个数据过期以后,用户会看到什么
  • 这个数据能不能接受短时间不一致
  • 这个 key 失效时,后端会不会被瞬间打穿

例如验证码和登录冷却时间,过期要短,而且必须精确;首页推荐缓存则可以粗一点,但最好加版本号;用户会话如果交给 Redis,就要先想清楚续期策略,不然用户明明没退出,session 却被你被动清掉了。

所以过期时间不是孤立参数,它其实是在表达业务容忍度。

调试时一定要留一条人工可读路径

我后来给团队提过一个很朴素的要求:线上出问题时,运维或者开发应该能在一分钟内凭肉眼判断某个 key 是什么。

这意味着:

  • 不要把关键语义全压缩成缩写
  • 需要版本切换的数据,要把版本号写进 key
  • 需要人工排查的数据,要能按前缀聚类

Redis 很快,但排障慢一点,成本就会立刻回来。尤其 2014 年那个阶段,Node.js 项目里很多辅助脚本、后台接口还不成熟,key 结构本身就是最可靠的说明书。

最后留下的一条习惯

如果今天让我再回到那几年写 Node.js + Redis,我还是会先写一页最简单的 key 约定,再开始接业务。因为你一旦允许每个模块自己决定 key 怎么起、TTL 怎么配,Redis 迟早会从缓存层变成“没人敢动的神秘角落”。

能跑起来只是第一步,能让三个月后的自己还看得懂,才算真正设计过。