11 月 12 日星期二清晨,Redis 的 DevOps 团队开始收到来自我们在 Amazon Web Services 欧洲中部区域(德国法兰克福)生产集群的大量警报。进一步检查后,他们意识到 AWS eu-central-1 数据中心发生了重大故障,这在AWS 状态页面上得到确认,并最终被媒体报道。
对我们来说,云服务故障并不新鲜。自 2013 年初以来,我们一直在运行生产环境的 Redis 集群,在此期间经历了超过 3,000 次实例故障和 100 多次完整数据中心故障。我们深切感谢云服务提供商为稳定其基础设施所做的努力,但我们也知道故障是不可避免的。因此,我们多年来投入了大量的工程资源,以确保我们的Redis Enterprise Cloud 服务能够提供业界领先的五个九 (99.999%) 可用性。
在分享我们如何克服故障的细节之前,让我们快速了解一下 Redis Enterprise Cloud 的架构。该服务在所有三个主要的公共云(AWS、Microsoft Azure 和 Google Cloud)和区域中部署和管理多个 Redis Enterprise 集群。每个Redis Enterprise 集群以多租户和隔离的方式管理多种不同配置的数据库(例如:单实例 Redis、高可用性 Redis、仅主节点的 Redis 集群以及高可用性 Redis 集群)。我们喜欢将其视为 Redis 数据库的编排平台。这意味着我们的一个集群发生故障可能会影响数百甚至数千个客户的数据库。
考虑到风险,我们推荐采用多可用区 (multi-AZ) 数据库配置,以帮助客户避免因基础设施故障(例如周二发生的故障)导致的数据库宕机。
在这个特定案例中,尽管我们所有的 AWS eu-central 集群都受到了影响,但我们所有的客户都部署在多个可用区中,因此这次故障并未影响集群的运行和可用性——即便在一个集群中,15 个节点中有 5 个节点发生了故障!此外,数百次自动故障转移事件顺利进行,没有发生任何数据丢失(当然),也没有收到一个紧急支持工单。少数用户抱怨执行某些管理操作花费的时间比预期长,但在这种故障期间这并不令人意外。
这怎么可能?以下是在多可用区配置中运行 Redis Enterprise 的原则
1. 内存复制(In-memory replication)。所有 Redis Enterprise 数据库都使用纯内存复制(我们贡献回 OSS 项目的一项功能,即将成为 Redis 6.0 的一部分)。内存复制使复制速度提高一倍,从而最大程度地减少了 Redis 暴露于双重故障事件的时间。
2. 同一数据集(哈希槽)的主实例和副本实例部署在不同的节点上。在多可用区部署中,它们也被部署在不同的可用区。
3. 每个集群节点都连接到外部持久化内存,以便在发生整个集群故障时能够快速恢复。(幸运的是这次没有发生。)
4. 我们的集群始终包含奇数个节点;这种设计使我们能够处理脑裂(split-brain)情况,例如网络分裂事件。
5. 基于同样的原因,在多可用区配置中,我们的集群部署在奇数个可用区中。
6. 我们确保每个可用区中部署的节点数量始终少于集群节点总数的一半。这保证了单个可用区故障不会导致法定人数丢失。
典型的 Redis Enterprise Cloud 多可用区配置可能如下所示
每个现代数据库都应该提供多可用区能力,但这本身不足以保证 99.999% 的可用性。如果没有真正的 Active-Active 多区域部署,让客户能够从完整的区域故障中立即恢复,就无法实现五个九的可用性,即每月宕机时间少于 26.3 秒。下图总结了我们通过 Redis Enterprise Cloud 提供的服务水平协议 (SLA) 类型。
当一项我们辛勤构建的功能在极端和意外的生产条件下按预期工作时,总是令人欣慰的。此次事件再次证明了 Redis Enterprise 如何能够作为关键任务用例的主数据库使用,特别是对于那些要求在极高吞吐量下实现亚毫秒级延迟的客户。