生产环境最佳实践清单
本章用于上线前复盘。不是每项都要立即实现,但每项都应该有明确答案。
1. 数据角色
- 这个键是缓存、会话、队列、锁,还是业务事实?
- 键丢失后能否重建?
- 允许多长时间的数据陈旧?
- Redis 不可用时选择降级、拒绝请求还是继续处理?
2. 键和值
- 使用一致命名空间,例如
应用:环境:模块:实体:id。 - 不在键名中暴露密码、令牌和敏感个人信息。
- 限制键和值大小。
- 大集合使用分页、范围查询或 SCAN,不一次全部读取。
- Cluster 环境提前检查多键操作的槽位。
3. TTL 与内存
- 缓存和临时状态设置 TTL。
- 批量缓存加入随机 TTL 抖动。
- 明确 Redis 的
maxmemory和淘汰策略。 - 监控
used_memory、evicted_keys和大键。 - 不依赖“内存应该够用”的猜测。
4. 连接
- 应用启动时建立客户端,HTTP 请求之间复用。
- 每个客户端都监听
error。 - 配置合理的连接和命令超时。
- 重连使用退避和随机抖动。
- 只有 Pub/Sub、阻塞命令或独占状态需要额外连接或池。
- 退出时先停止流量,再
close();必要时才destroy()。
5. 安全
- Redis 不直接暴露到公网。
- 使用 ACL 最小权限账号。
- 云环境或不可信网络启用 TLS。
- 凭据放在环境变量或密钥管理服务,不提交到 Git。
- 普通应用账号不授予
FLUSHALL、CONFIG等危险权限。 - 日志隐藏连接 URL 中的密码和敏感值。
6. 性能
- 使用
Promise.all()利用自动流水线,但限制并发批量。 - 选择能直接表达业务操作的数据类型。
- 避免
KEYS *和不受限的全量读取。 - 监控慢命令,而不是只根据平均延迟判断。
- 性能优化前做基准测试,包含真实值大小和并发量。
7. 一致性与并发
- 优先使用原子命令。
WATCH冲突后必须重试,并限制次数。- Lua 脚本保持短小,检查 Cluster 键槽。
- Cache-Aside 更新通常采用“更新数据库后删除缓存”。
- 关键幂等性使用数据库唯一约束等最终防线。
- 读副本场景接受复制延迟,或让强一致读取走主节点。
8. 可观测性
建议监控:
- 缓存命中率与未命中率。
- Redis 命令 P50、P95、P99 延迟。
- 超时、连接失败和重连次数。
- 当前连接数、阻塞客户端数。
- 服务端 CPU、内存、淘汰键和过期键。
- 主从复制延迟和故障转移。
- Cluster 槽位和节点健康状态。
Node-Redis 还支持 OpenTelemetry 指标和 Node.js diagnostics_channel。引入前应先理解团队现有的指标 SDK、Exporter 和采集平台,避免只初始化客户端侧功能却没有实际导出指标。
9. 故障演练
至少验证:
- Redis 进程停止时应用如何响应。
- 网络中断和恢复时是否发生请求堆积。
- 密码错误或权限不足时日志是否清晰。
- Sentinel/Cluster 故障转移期间是否出现不可接受的错误。
- Redis 全部缓存丢失后,数据库能否承受回源流量。
- 进程收到
SIGTERM时能否正常关闭连接。
10. 版本与文档
- 锁定 Node-Redis 依赖版本并审查升级说明。
- 记录 Redis 服务端版本和部署模式。
- 不混用 v3 回调 API、v4/v5/v6 示例。
- 新命令先确认服务端版本支持,再确认 Node-Redis 类型支持。
- 把团队约定的键命名、TTL、降级策略写入项目文档。
推荐的渐进式上线顺序
- 先将 Redis 用作可丢失、可重建的查询缓存。
- 加入命中率、延迟、错误率和内存监控。
- 演练 Redis 不可用和缓存全失效。
- 再逐步用于会话、限流、幂等或消息场景。
- 只有实际容量或可用性要求出现后,再引入 Sentinel、Cluster 和客户端缓存。