Normalized Cache、HTTP缓存与Apollo APQ的区别及共存合理性探讨
关于Apollo GraphQL中Normalized Cache与APQ共存的疑问
某Android应用基于GraphQL(Apollo)框架,为减少后端查询次数已实现Normalized cache。之后了解到APQ(Automatic Persisted Queries)机制,想确认自己“APQ是后端侧的缓存替代方案”这个理解是否正确?
个人梳理的同时启用两者的查询流程如下:query -> 本地缓存校验 -> 无缓存则发送请求至服务器 -> 服务器APQ无对应记录则执行查询并返回结果,同时将结果存入APQ -> 客户端接收响应后存入Normalized cache
疑问:
- 同时实现两者是否合理?
- 是否属于冗余设计?
- 为何要同时部署Normalized cache与APQ?
解答
首先纠正你的核心误解:APQ不是后端侧的缓存替代方案,它和Normalized Cache解决的是完全不同层面的问题,两者共存不仅合理,反而能形成互补的性能优化效果。
两者的核心定位差异
Normalized Cache(客户端归一化缓存)
这是客户端侧的缓存机制,核心作用是避免不必要的网络请求。它会把GraphQL查询返回的结果按对象粒度拆分、去重存储,比如多个查询都用到同一个用户信息时,本地只会存一份。当客户端再次发起相同或关联查询时,直接从本地缓存读取数据,完全跳过网络请求环节,能极大提升页面响应速度、节省用户流量。APQ(自动持久化查询)
这是客户端与服务器协同的请求优化机制,核心作用是缩小请求体积。它的逻辑是:- 客户端第一次发送某条查询时,会带上完整的查询字符串;
- 服务器存储该查询的哈希值与查询内容的映射关系;
- 后续客户端再发起同一条查询时,只需要发送查询的哈希值,服务器通过哈希快速找到对应的查询内容并执行,返回结果。
它优化的是“必须发起网络请求”时的传输效率,尤其是复杂查询场景下,能把几KB甚至几十KB的查询字符串压缩成几十字节的哈希,大幅降低带宽消耗,同时也能减少查询字符串泄露的风险。
两者共存的合理性
完全不属于冗余设计,因为它们的优化链路是递进的:
- 首先由Normalized Cache拦截请求:能从本地取数据就不发请求,从根源减少后端查询次数;
- 当本地无缓存必须发请求时,APQ优化请求本身的传输成本,让网络交互更高效。
举个实际场景:
- 第一次请求某页面数据:客户端无缓存,发送完整查询字符串,服务器执行查询并存储APQ映射,返回结果后客户端存入Normalized Cache;
- 第二次进入同一页面:客户端直接读取本地缓存,无需发起任何网络请求;
- 第三次请求关联页面的新数据:客户端无对应缓存,发送查询哈希值,服务器快速匹配查询并执行,返回结果后客户端更新本地缓存。
两者配合能最大化GraphQL客户端的性能表现,既减少网络请求的次数,又优化必要请求的传输效率。
内容的提问来源于stack exchange,提问作者Sirop4ik
相关产品推荐
相关产品推荐

