编者按:本文是高容量、高可用性缓存系列文章的第一篇:
- 使用NGINX Plus缓存集群实现共享缓存,第1部分(本文)
- 使用NGINX Plus缓存集群实现共享缓存,第 2 部分
本文已更新为介绍NGINX Plus API。该API取代了本文原先讨论的独立扩展状态模块,后者现已弃用。
如何使用NGINX或NGINX Plus构建大容量、高可用的缓存集群?本系列共分两部分,介绍实现这一目标的不同方法,本文是第一部分。可通过上方链接查看第二部分。(除非另有说明,这些方法同样适用于NGINX Open Source和NGINX Plus,但为简洁起见,本文仅使用NGINX Plus这一名称。)
NGINX Plus 缓存概述
NGINX Plus可作为代理缓存服务器运行,位于源服务器与远程客户端之间。NGINX Plus管理发往源服务器的流量,并缓存(存储)常用且不变的资源。这样,当客户端请求这些资源时,NGINX Plus可直接响应,从而减轻源服务器的负载。NGINX Plus代理缓存通常部署在源服务器附近的数据中心,也可以采用类似CDN的方式部署在全球分布的PoP中。
内容缓存是一个比想象中更复杂的主题。在继续阅读本文之前,建议先熟悉一些基本的缓存技术:
- NGINX Plus缓存机制:核心配置以及缓存加载器和缓存管理器进程的作用
- 精细调整缓存时间:采用微缓存等做法,控制内容的缓存方式以及缓存过期后的刷新方式
为什么NGINX Plus不使用共享磁盘进行缓存?
每台NGINX Plus服务器都作为独立的Web缓存服务器运行。目前没有技术手段可在多台NGINX Plus服务器之间共享基于磁盘的缓存;这是有意为之的设计决策。
将缓存存储在高延迟且可能不可靠的共享文件系统中并非合理的设计选择。NGINX Plus对磁盘延迟较为敏感。尽管线程池功能会将read()和write()操作从主线程卸载,但当文件系统速度较慢且缓存I/O较高时,大量线程仍可能使NGINX Plus不堪重负。要在多个NGINX Plus实例之间维护一致的共享缓存,还需要使用集群范围的锁来同步相互重叠的缓存操作,例如填充、读取和删除。最后,共享文件系统会给缓存带来不可靠性和不可预测的性能,而可靠性和稳定一致的性能对缓存至关重要。
为何在多台NGINX Plus服务器之间共享缓存?
虽然共享文件系统并不是一种理想的缓存方式,但仍有充分理由在多台NGINX Plus服务器之间缓存内容,并且每种理由都有相应的实现方法:
- 如果主要目标是创建超大容量缓存,请将缓存分片(分区)到多台服务器上。本文将介绍这种技术。
- 如果主要目标是在尽量降低源服务器负载的同时实现高可用性,请使用高可用共享缓存。有关此技术,请参阅配套文章(即将发布)。

对缓存进行分片
对缓存进行分片是指将缓存条目分布到多个Web缓存服务器上。NGINX Plus缓存分片使用一致性哈希算法为每个缓存条目选择一台缓存服务器。图中显示了分片到三台服务器上的缓存(左图)在一台服务器停机(中图)或添加另一台服务器(右图)时的变化。

总缓存容量等于各服务器缓存容量之和。由于每项资源仅由一台服务器尝试缓存(同一资源不会存在多个相互独立的副本),因此可以尽量减少对源服务器的访问。

此模式具有容错能力:如果有N台缓存服务器,其中一台发生故障,只会损失缓存总量的1/N。一致性哈希会将这部分“丢失的缓存”均匀分布到其余N –1台服务器上。相比之下,较简单的哈希方法会将整个缓存重新分布到其余服务器上,导致在重新分布期间几乎丢失所有缓存。
执行一致性哈希负载均衡时,使用缓存键(或用于构造该键的部分字段)作为一致性哈希的键:
upstream cache_servers { hash $scheme$proxy_host$request_uri consistent;
server red.cache.example.com;
server green.cache.example.com;
server blue.cache.example.com;
}可以使用NGINX Plus中的主动-被动高可用性解决方案、轮询DNS或keepalived等高可用性解决方案,在负载均衡器(LB)层分配入站流量。
优化分片缓存配置
您可以选择以下两种缓存分片配置优化方案之一。
合并负载均衡器层和缓存层
可以将LB层和缓存层合并。在此配置中,每个NGINX Plus实例上运行两个虚拟服务器。负载均衡虚拟服务器(图中的“LB VS”)接收来自外部客户端的请求,并使用一致性哈希将请求分发到集群中的所有NGINX Plus实例,这些实例通过内部网络连接。每个NGINX Plus实例上的缓存虚拟服务器(“Cache VS”)在其内部IP地址上侦听分配给该实例的请求,将请求转发到源服务器并缓存响应。这样,所有NGINX Plus实例都可以充当缓存服务器,从而充分利用缓存容量。

配置一级“热”缓存
或者,可以在前端LB层为访问量极高的内容配置一级缓存,并将大型共享缓存用作二级缓存。这样可以提升性能,并在二级缓存层发生故障时减轻对源服务器的影响,因为只需随着一级缓存中的内容逐渐过期而刷新相应内容。

如果缓存集群正在处理大量热门内容,容量较小的一级缓存可能会出现很高的内容更替率。换言之,对有限缓存空间的需求过高,导致内容还未来得及用于响应哪怕一次后续请求,就已被逐出缓存(以便为最近请求的内容腾出空间)。
这种情况的一个指标是已提供内容与已写入内容的比率较低,这两项指标包含在NGINX Plus API模块报告的扩展统计信息中。它们显示在内置Served和Written字段中,这两个字段位于Caches选项卡的实时活动监控仪表板上。(请注意,NGINX Plus API模块和实时活动监控仪表板在NGINX Open Source中不可用。)
此屏幕截图显示,NGINX Plus写入缓存的内容多于从缓存提供的内容:

在这种情况下,可以微调缓存,使其仅存储最常请求的内容。proxy_cache_min_uses指令有助于识别此类内容。
总结
将缓存分片到多台NGINX或NGINX Plus Web缓存服务器,是构建超大容量、可扩展缓存的有效方法。一致性哈希可提供较高的可用性,确保某个缓存发生故障时,仅其负责的缓存内容失效。
本文的第二部分介绍了另一种共享缓存模式,该模式在两台NGINX或NGINX Plus缓存服务器上复制缓存。总容量受限于单台服务器的容量,但此配置具备全面的容错能力,即使一台缓存服务器不可用,也不会丢失任何缓存内容。
在自己的服务器上试用缓存分片,立即开始30 天免费试用,或联系我们,探讨您的用例。
关于作者

相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
