第13章 Memcached 代理基础设施示例与架构解析
功能内置代理基础设施示例基础设施示例本页通过图示示例,介绍如何使用 Memcached 内置代理搭建负载均衡的多节点缓存系统。关于内置代理的总体介绍,请参阅内置代理。memcached 代理是一个灵活、轻量、依赖很少的系统。任何 memcached 二进制文件都可以充当代理、缓存服务器,或两者兼而有之,方便我们根据应用需求灵活调整。代理中间件机器
flowchart TD A[Application] -->|memcached protocol|B B{Memcached Proxy} B -->D[Memcached] B -->E[Memcached] B -->F[Memcached]
flowchart TD A[Application] -->|memcached protocol|B B{Memcached Proxy} -->foo1 B -->bar1 subgraph foo1 [key prefix 'foo/'] FN1[memcached] FN2[memcached] FN3[memcached] end subgraph bar1 [key prefix 'bar/'] BN1[memcached] BN2[memcached] BN3[memcached] end
中间件架构“中间件机器”这种部署方式想必大家并不陌生:由一台或多台机器位于应用服务器和缓存存储节点之间。这种设计可以把缓存池配置集中管理,简化缓存客户端,同时集中维护代理服务器。每个缓存请求都先由代理服务器处理,再由代理按需将请求分发到后端服务器,并把结果返回给客户端。中间件优点缓存配置与缓存池维护集中化。团队无需修改、重启或向应用服务器推送配置,就能维护复杂的缓存结构。缓存客户端的复杂性转移到代理层。大多数 memcached 客户端都是“全功能”的:接收包含服务器列表的配置,自行计算哈希,并把请求直接分发到后端服务器。这通常是性能最好的方案。但使用一个极简的 memcached 客户端也有其价值。尤其当需要复杂功能时,为了改动而更新所有应用程序对团队来说是很大的负担,容易导致停滞,大家会尽量避免变更。可以在代理层实现“热 key 缓存”来提升性能。由于每个代理本身也是一个普通 memcached,因此可以构建“L1/L2”分层缓存。具体做法取决于你的需求,但这样做可以省去请求先经过代理所带来的额外网络请求延迟和 CPU 开销。中间件缺点读取数据必须先经过代理,增加了往返次数和延迟。没有代理时,一次对 memcached 的请求/响应包括:客户端发出写请求 memcached 读取请求 memcached 写出响应 客户端读取响应 而通过代理时,会引入额外的延迟环节:客户端发出写请求……等待网络……代理读取请求 代理发出写请求……等待网络……memcached 读取请求 memcached 写出响应……等待网络……代理读取响应 代理写出响应……等待网络……客户端读取响应 注意,实际情况因实现而异:代理中的热缓存、未命中时从远程缓存池获取等机制,仍可能提升整体性能。性能不理想,尤其是对带宽占用高的大型缓存。如果涉及的机器都足够快,高请求速率尚可承受。但如果缓存数据很大(数百 KB 到数 MB),且代理数量少于缓存服务器数量,带宽很快就会成为瓶颈。memcached 的一个隐性优势在于:其分布式直连客户端的特性,使缓存池的总带宽容量随服务器数量线性扩展。如果你需要 10 台服务器来容纳全部缓存数据,却只需 2 台代理来做“前端”,那么带宽瓶颈就在代理,而不在后端服务器。应用 Sidecar
flowchart TD subgraph app [Application Host] App[Application] -->|simplified memcached protocol| Prox{Memcached Proxy} end Prox --> foo subgraph foo [key prefix 'foo/'] FN1[memcached] FN2[memcached] FN3[memcached] end Prox --> bar subgraph bar [key prefix 'bar/'] BN1[memcached] BN2[memcached] BN3[memcached] end
Sidecar 架构在“sidecar”式部署中,每台应用服务器都在本机运行一个代理(可通过二进制部署、容器等方式实现)。这在前置代理与内嵌于应用中的胖客户端之间提供了一个折中方案。Sidecar 可以把缓存池配置、请求分发、key 分布、代理升级等工作从应用客户端中抽象出来,简化维护。也可以混合使用这两种方式:某些应用适合本地 sidecar(高带宽场景),某些则适合集中式缓存池(缓存使用较少,可简化部署)。Sidecar 优点扩展能力与无代理的 memcached 类似:带宽和请求速率不受限制。虽然比维护一个小型集中式缓存池工作量更大,但仍可以在不改动应用服务器的情况下更新代理。应用仍可使用简化版客户端。Sidecar 缺点必须在每台应用服务器上管理部署,而不是集中管理一个缓存池。给应用服务器增加一定 CPU 开销。仍需要额外的系统调用:客户端到本地代理,再到远程服务器并返回。本地连接的开销通常很低,但必须实际验证,因为“容器系统”可能带来显著开销。缓存分层代理
flowchart TD App[Application] --> foo subgraph foo [cache pool] C1[memcached] C2[memcached] C3[memcached] end foo --> rem subgraph rem [remote pool] R1[memcached] R2[memcached] R3[memcached] end
缓存分层架构分层缓存是一种用代理节点替换现有 memcached 服务器池的架构。客户端仍使用标准客户端,负责哈希 key 并分发到各代理节点,而代理节点本身则执行额外的工作。这些额外工作可以是:把 set 命令复制到远程缓存池、未命中时从远程缓存池获取,或为特定命名空间从远程缓存池获取数据。如果你想用更便宜的服务器存储长尾冷数据,或者某些 key 命名空间的数据量大但请求率不高,这种方案就很合适。它也是把代理引入现有 memcached 缓存池的一个良好切入点。缓存分层优点适用于已部署 memcached 但希望增加冗余、扩展等能力的场景。把最常用的缓存数据保留在顶层,保证性能。缓存分层缺点需要更复杂的应用客户端。缓存池配置需要在两处管理(应用客户端和 memcached 代理)。运行内置代理内部架构