在Google Cloud上部署Redis,很多团队首先想到的是自己创建Compute Engine虚拟机,然后安装Redis、配置持久化、复制、故障切换和监控。但对于大多数SaaS应用来说,自己维护一套Redis集群意味着额外的运维工作。Google Cloud提供的Memorystore,就是把Redis等内存数据库作为托管服务提供给应用使用。
Memorystore的价值并不是“Redis速度更快”,而是把Redis服务器本身的部署、基础设施维护、高可用、故障切换和监控等工作交给Google Cloud。当前Google Cloud需要特别区分Memorystore for Redis和Memorystore for Redis Cluster。前者适合传统Redis实例以及通过副本扩展读取的场景,后者则采用真正的分片集群架构,把数据分布到多个shard中。
对于普通SaaS缓存,如果数据量并不大,业务也没有明显的Redis吞吐瓶颈,并不需要一开始就使用Redis Cluster。一个普通的Memorystore for Redis实例就可能足够。它可以作为数据库缓存、Session存储、限流计数器、临时状态存储以及其他短生命周期数据的高速访问层。
如果业务进一步增长,需要更多内存容量或者更高的并行吞吐量,Redis Cluster才开始体现价值。Memorystore for Redis Cluster通过shard进行数据分片,每个shard有一个primary节点,并可以配置多个replica。不同shard负责不同的keyspace,因此系统能够通过增加shard水平扩展容量和吞吐能力。Google目前的Cluster架构支持每个shard配置0到5个replica。
这也意味着Redis Cluster不能简单理解成“把一个Redis服务器换成几台Redis服务器”。应用程序必须使用支持Redis Cluster协议的客户端,并能够正确处理节点发现、slot变化、primary切换以及连接重新建立。Memorystore for Redis Cluster提供discovery endpoint,客户端通过它发现实际的集群节点。
高可用方面,普通Memorystore for Redis的Standard Tier通过primary和replica实现复制与自动故障切换。如果primary发生故障,Google的健康监控机制会选择可用副本进行故障转移。对于配置了read replicas的实例,副本还可以承担读取请求。
这里有一个非常重要的概念:Redis副本通常采用异步复制。因此,副本并不一定在任何时刻都与primary完全同步。如果应用把读取请求发送到read replica,可能读到稍早的数据。Google也明确指出,如果应用要求“写入后立即读取同一数据”的read-your-write一致性,就应该使用primary endpoint。
Memorystore for Redis Cluster的高可用方式也不是原文所谓的“Active-Active”。一个高可用Cluster通常是在同一个region内,把shard的primary和replica分布到不同zone。这样发生zone级故障时,可以通过replica进行自动故障切换。Google明确建议生产环境优先使用multi-zone配置,并为每个shard至少配置一个replica。
如果企业确实需要跨区域能力,Memorystore for Redis Cluster还提供cross-region replication。这里的架构与Active-Active完全不同:一个region中的primary cluster负责读写,其他region中的secondary cluster通过异步复制获得数据。secondary可以承担读取请求;当发生区域故障或者计划中的区域迁移时,可以通过switchover或detach等操作让secondary承担新的读写职责。
这种设计特别适合灾难恢复和跨区域读取,而不是把两个区域当成完全独立、同时接受写入的Redis数据库。由于复制是异步的,如果primary发生灾难时secondary尚未完全追上,就存在部分数据没有复制过去的可能。因此,跨区域Redis架构必须根据业务能够接受的RPO来设计,而不能简单地认为“部署两个区域就等于零数据丢失”。
跨区域复制还有实际成本。secondary cluster本身需要付费,同时不同region之间的数据复制还会产生网络费用。因此,一个普通SaaS后台如果所有用户都集中在一个主要区域,仅仅为了“看起来全球高可用”而部署多个Redis区域,很可能增加复杂度和成本,却没有真正解决业务问题。
Redis缓存部署首先应该从数据性质开始判断。最典型的是数据库查询缓存,例如产品信息、配置数据、统计结果等。此时Redis中的数据应该被视为可以重新生成的缓存,而不是唯一数据源。MySQL或其他持久化数据库才是最终事实来源。
Session存储则有所不同。如果Redis保存用户登录Session,那么Redis故障可能直接影响用户登录状态。此时应该考虑高可用配置、连接重试以及Session恢复策略,而不能简单使用一个没有副本的Redis实例。
限流、验证码计数、短期任务状态、排行榜等数据也非常适合Redis,但每一种数据对一致性和持久性的要求不同。例如一个API限流计数器丢失一些数据通常只是短时间内限流策略变化,而订单状态、支付状态等核心业务数据就不应该因为Redis故障而永久丢失。
因此,一个重要原则是:不要把Redis当成MySQL的替代品。
Redis非常适合快速访问,但它是内存数据库。对于缓存场景,最合理的设计通常是:
用户请求
↓
PHP / SaaS应用
↓
Redis
├── 命中 → 直接返回
│
└── 未命中
↓
MySQL
↓
写入Redis
↓
返回结果
这种架构下,即使Redis中的缓存全部消失,应用仍然能够从MySQL重新生成缓存。这样Redis故障不会直接变成数据灾难。
PHP应用连接Memorystore时,还需要考虑网络位置。Memorystore不是一个应该直接暴露给互联网用户访问的Redis服务器。应用服务器应该通过Google Cloud的私有网络路径访问它,并按照对应产品的网络要求配置VPC、Private Service Connect或其他网络连接方式。Memorystore for Redis Cluster创建实例前也需要完成相应的网络配置。
安全方面也不能简单理解成“打开IAM就安全了”。Google Cloud IAM主要负责Google Cloud资源和API层面的权限,而Redis自身的数据访问还涉及Redis ACL等机制。尤其是跨区域复制时,Cluster的ACL策略不会自动同步到secondary,需要分别维护。
应用层同样需要做好连接管理。Redis服务器发生故障切换时,原有TCP连接可能被断开,因此PHP程序不能假设一个Redis连接永远有效。生产环境应该使用合理的连接超时、重试策略,并避免无限重试把Redis故障进一步放大成PHP-FPM连接堆积。
对于PHP SaaS系统,还应该特别注意缓存击穿问题。如果一个热门Key突然过期,大量PHP请求可能同时访问MySQL重新生成同一个缓存。Redis本身没有解决这个问题,应用可以根据业务采用锁、single-flight、提前刷新或随机TTL等策略降低瞬时数据库压力。
缓存过期时间也不应该全部设置成相同的固定值。大量Key在同一时间写入、又在同一时间过期,可能形成所谓的cache avalanche。适当加入TTL随机抖动、分散刷新时间以及对热点Key采用特殊策略,通常比简单设置一个统一TTL更加稳定。
监控方面,至少应该观察Redis内存使用、连接数、命令延迟、吞吐量、命中率、eviction、CPU以及复制状态。对于Cluster,还应该关注各shard的负载是否均衡。Google Cloud提供Cloud Monitoring,可以用于观察Memorystore相关指标。跨区域Cluster还可以观察复制延迟等指标,例如secondary replication offset差异。
Redis的容量也不能按照“机器内存有多少就能存多少数据”计算。Redis除了实际Key和Value,还存在对象、数据结构以及内部管理开销。Cluster还涉及shard分布和replica,因此容量规划必须结合实际数据结构、Key数量、Value大小、TTL、访问模式和峰值负载进行压测。
对于开发环境,单区域、较小容量的Redis通常已经足够。对于生产环境,如果Redis故障会影响核心业务,则应该考虑Standard Tier或Cluster的多zone高可用配置。只有当数据量、吞吐量、读请求规模或者灾难恢复要求真正达到相应程度时,才需要进一步考虑Redis Cluster和跨区域复制。
如果业务只是一个普通的PHP SaaS网站,例如PHP-FPM、MySQL和Redis组成传统后台,完全没有必要一开始就建立复杂的全球Redis架构。一个合理的起点往往是单region的高可用Memorystore,让PHP应用和Redis尽可能处于相同区域,减少网络延迟和跨区域流量。随着业务增长,再根据实际指标增加replica、shard或者跨区域灾难恢复能力。
最终,Memorystore真正解决的是“谁来维护Redis基础设施”的问题,而不是替应用决定缓存架构。单实例、Standard Tier、read replicas、Redis Cluster以及cross-region replication解决的是不同层次的问题。对于SaaS系统来说,正确的顺序应该是先确定Redis保存什么数据,再确定一致性、可丢失程度、容量和吞吐需求,最后选择合适的Memorystore架构。
Redis最理想的位置,是成为数据库和应用之间一个高速、可控制、可以失效后重建的缓存层。当架构能够接受Redis暂时不可用、缓存可以重新生成,并且应用能够正确处理连接断开和故障切换时,Memorystore才真正发挥了它作为托管Redis服务的价值。
分享 Facebook |
X |
Whatsapp |
Linkedin
捐助(Paypal): https://www.paypal.me/observeccp
订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP
责任编辑:雨轩 来源:中国观察 转载请注明作者、出处並保持完整。
今日热点:
近期焦点:
推荐阅读: