nginx通过openresty+lua直连redis获取数据并响应,完全绕过tomcat等应用服务器,显著缩短响应路径;利用lua-resty-redis模块实现原生访存,配合shared_dict本地缓存、分级key设计、ttl控制、订阅更新及预压缩/预解析等机制,达成高性能、低延迟、可运维的动态内容交付。

直接让 Nginx 绕过应用服务器,从 Redis 读取并返回数据,是缩短响应路径最有效的方式——关键在于用 OpenResty + Lua 实现“Nginx 原生访存”,而不是依赖 proxy_pass 转发到后端再查 Redis。
用 Lua 直连 Redis,跳过整个后端服务链
传统 proxy_cache 只能缓存后端响应,仍需调用 Tomcat/PHP 等;而通过 lua-resty-redis 模块,Nginx worker 进程可直连 Redis 执行 GET/SET,完全不占用后端线程:
- 安装 OpenResty(含 Lua 环境和常用模块),而非标准 Nginx
- 在 location 中嵌入 Lua 脚本:先查 Redis → 命中则 ngx.exit(200) 并输出内容;未命中则 proxy_pass 到后端,并在 body_filter_by_lua* 阶段写回 Redis
- 配合 lua_shared_dict 做本地内存缓存(如连接池、热点 key 标记),减少 Redis 往返
对频繁变动数据做分级缓存与精准失效
不是所有数据都适合长缓存,重点在于“变但有规律”:比如用户个人中心页每分钟更新一次头像/未读数,但结构固定。此时应:
Redis 缓存和数据结构管理技能。通过自然语言操作 Redis,支持 String、Hash、List、Set、ZSet、Stream 等数据结构操作。当用户提到 Redis、缓存、消息队列、会话存储时使用此技能。
- Redis 中按业务维度分 key 存储,例如 user:1001:profile、user:1001:stats,避免整页缓存导致局部更新需全刷
- 设置合理 TTL(如 60s),配合定时任务(lua_timer_at)主动刷新,而非被动等待过期
- 后端修改数据时,同步触发 PUBLISH user:1001:update,Nginx 用 redis.subscribe 监听并清理对应 key(需启用 lua-resty-redis 的订阅能力)
压缩传输 + 预解码,降低网络与解析开销
高频访问的 HTML 片段或 JSON 数据,体积常达几 KB。若每次从 Redis 取出后还要 gzip 解压、JSON 解析再渲染,反而拖慢响应。建议:
- 后端生成时即用 lua-zlib 压缩内容,存入 Redis 的 value 为
{"len":1248,"body":"eJz..."} - Nginx Lua 层根据 len 字段判断是否需解压:len > 1024 才调用 zlib.inflate,否则直传
- 对 JSON 类响应,可预解析成 Lua table 存于 shared_dict,后续请求直接 ngx.encode_json 输出,省去重复 decode/encode
单 worker 定时更新 + 可配置化管理
避免多 worker 同时刷新同一 URL 导致 Redis 写风暴:
- 用 ngx.worker.id() == 0 限定仅 worker 0 执行定时拉取与写入 Redis
- 将缓存策略外部化:URL、TTL、刷新间隔等通过管理后台下发配置,Nginx 用 resty-http 轮询获取,动态 reload 规则
- 关键接口加 X-Cache: HIT/MISS/STALE 和 X-From: redis/nginx/backend 头,便于线上问题快速归因










