2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

Nextdoor 零停机 Redis 迁移实践

  • 2020-03-04
  • 本文字数:3012 字

    阅读完需:约 10 分钟

Nextdoor零停机Redis迁移实践

背景介绍

在 Nextdoor,我们大量使用了 Redis 这个高性能的内存数据存储,为我们的许多服务提供低延迟的数据访问。现在,我们通过 ElastiCache 使用着十几个不同的 Redis 实例;其中有许多对应于我们的微服务或我们的主要应用 Django 中的特定用例,比如 AB 测试跟踪。它们可以作为数据的真实来源,也可以纯粹作为缓存来提升性能。


除了少数例外,我们大多数的 Redis 部署最初创建时都是主副本节点的单一实例,这样,我们可以保证单个节点的故障不会造成数据的永久损失,同时,我们可以在故障转移时继续提供服务。此外,通过将特定的用例隔离到它们自己的 Redis 实例,我们还可以实现不同的故障模式,限制单个问题的影响。虽然这听起来很像高可用性数据存储的要素,但我们意识到,我们还没有完全做到这一点,特别是当我们的一些实例达到了其负载能力的极限时。在这篇文章中,我们将解释可用性方面的一些缺陷,这些缺陷最终导致我们重新构建我们的整个实例集,以及我们用来监督这个迁移过程使其不影响任何核心服务的方法。


单一主副本配置的不足之处

例如,让我们考虑这样一个场景:一个 Redis 实例由一个主节点和一个副本节点组成,在接近 CPU 最大处理能力时触发了故障转移(可能是副本节点遇到了硬件问题,需要准备一个新节点)。主节点现在开始获取其自身的快照,并将其发送给新的副本节点,这将导致主服务器达到最大处理能力。此时,到这个 Redis 实例的请求开始超时,可能一些用户开始看到功能受限。我们甚至可以更进一步;如果我们的 Redis 客户端不够智能,无法恰当地处理这些超时,可能会引起连锁反应,我们可能会备份关键服务的所有流量。


虽然这只是一个特殊的例子,但我们已经确定了一组使我们的 Redis 配置变得脆弱的关键的底层问题。一方面,CPU 利用率成为保证可用性的一个重大瓶颈,这不适合那些一天中经常出现突发事件和流量峰值的服务。然而,更重要的是,没有一种简洁的方法可以用来扩展我们的 Redis 实例以满足我们的服务需求(只能购买更大的实例类型,但这不是一个很有远见的解决方案)。


幸运的是,这类问题相对比较常见,而 Redis 本身提供了一种可以解决这个问题的集群模式。使用集群,我们的数据分布在多个分片上,每个分片拥有整个键空间的一部分。从可用性的角度来看,这是有好处的,因为它允许我们在必要时水平地扩展我们的 Redis 实例(只需向集群添加新节点),而不需很长的停机时间。此外,上述重大问题的影响也有所减轻;如果一个分片达到了 CPU 处理能力,那么剩下的分片可以继续正常运行,因此,问题仅会影响一小部分请求。

制定迁移策略

随着规模的不断扩大,我们开始着手升级我们所有的 Redis 部署,以下是几个需要优先考虑的事项:


  • 切换到集群化 Redis:这可以满足我们的水平扩展需求,并从根本上解决上述所有问题。

  • 升级旧的实例类型:我们的大多数 Redis 实例都错过了与新硬件结合的性能提升,因此升级可以进一步缓解我们对高 CPU 利用率的担忧。

  • 尽量减少迁移过程的停机时间:由于我们的许多 Redis 实例都是我们的核心服务的组成部分,所以迁移到新实例的过程中不影响会员的体验很重要。


在这里,我们遇到了最大的挑战:弄清楚迁移的过程。虽然我们非常清楚我们的最终状态应该是什么,但是,最后一个要求——最小化停机时间——排除了许多我们可能最终用来切换到新实例的方法。值得注意的是,我们迁移到集群 Redis 的目标意味着我们可能无法直接通过 AWS,因为 AWS 只支持在不更改集群模式的情况下升级引擎版本(例如,从非集群到非集群或从集群到集群)。为此,我们最好的选择是手动创建一个新的单分片的 Redis 集群,从旧实例的备份中恢复它,然后在稍后扩展分片的数量——在几个小时的迁移期间里不能接受写流量。为了实现这三个目标,我们需要一点创造力来帮助我们实现迁移。


大约在这个时候,我们刚刚开始研究 Envoy 的用法,这是 Lyft 构建的一个分布式代理,它为基于微服务的大型架构提供了更好的可观测性。Envoy 使我们能够在服务中添加故障注入和健康检查等功能,从而可以测试推送的稳定性,只需将其与这些服务一起部署即可。它还可以作为一个 Redis 代理,更具体地说,它可以跨不同的上游集群处理 Redis 请求的路由。在这里,我们找到了大规模 Redis 迁移所需的完美抽象;通过将 Envoy 作为中介添加到所有的 Redis 实例,我们可以更智能地协调将数据迁移到新的 Redis 集群的过程,同时继续为用户提供服务。为了说明这一点,让我们按顺序看下从旧实例切换到新实例所需的全部事件。

第一步:将所有流量代理到旧实例


Envoy 作为我们服务的跨斗(sidecar)Docker 容器运行,我们只需修改服务,将 Envoy 视为其上游 Redis 主机。Envoy 负责侦听 Redis 请求的特定端口,它直接将请求(读和写)转发给实际的旧 Redis 实例。重要的是,除了修改 Redis 的地址外,不需要在客户端进行任何更改,客户端基本上不知道它的请求不会直接发送到 Redis(一个例外是原来的 Redis 实例已经集群化;在这种情况下,客户端可能需要改成使用普通的 Redis 客户端库,而不是集群化 Redis 库,因为 Envoy 的行为类似于“非集群化 Redis”)。

第二步:将写入镜像到新集群


在根据必要的规范配置好新的 Redis 集群之后,我们修改了 Envoy 的 Redis 侦听器定义,将其镜像或双写到新的集群化 Redis。这样,任何新的写入都可以同时写到旧的和新的 Redis 实例。请注意,Envoy 采用了双重写入的即发即弃模型,因此,它不会等着确认新集群的写入是否成功,但通常这里很少出现任何问题。这时,新的 Redis 集群仍然远远落后于旧的集群,但是我们已经比较确定,在实际同步之后,这两个集群不会再次出现差异。

第三步:将内容完整地回填到新集群


这一步是计算最密集的,需要扫描旧的 Redis 实例并将其所有内容复制到新实例。为了更有效率,我们使用了 RedisShake(一个来自阿里巴巴的优秀开源工具),并围绕它封装了我们自己的 ECS 服务来自动同步。请注意,与捕获快照非常相似,运行此脚本也有挂载 CPU 的能力,因此必须特别注意,使用合理的 QPS(即每秒查询次数)和设置来运行脚本,并且最好在低流量期间运行脚本。现在,这两个实例应该完全同步了,任何错过的双写都应该被捕获了。

第四步:验证并切换


为了确保这两个实例是同步的,我们运行 RedisFullCheck 工具,它经过几轮比较后可以区分旧实例和新实例之间存在差异的键,并将它们存储到 SQLite 数据库中。在我们的例子中,键的差异更可能是因为某个地方某个特定的 Redis 用法与 Envoy 不兼容(下面将描述这些不兼容),而不是因为回填脚本遗漏了写操作;这一步可能需要一些调查工作。一旦检查脚本结果没有问题,我们最后会再次更新 Envoy 侦听器配置,将所有的流量全部路由到新集群,并删除旧实例。

一些注意事项

使用上面的策略,我们成功地将所有的 Redis 实例迁移到一个最终状态,其中每个实例都是集群化的,并运行最新版本的 Redis。然而,在实践中,我们发现这种方法也有其局限性,特别是在 Envoy 的使用上。最重要的是,我们发现,Envoy 只支持散列到一个分片的 Redis 请求,它排除了所有与集群相关的命令(由于我们的大多数实例以前都不是集群化的,所以我们很幸运,没有很多这样的命令)。因而使用 Redis MULTI 命令的任何事务逻辑也不受支持。为了解决这个问题,我们修改了基于事务的代码,改为使用 Lua 脚本,它以与 Envoy 兼容的方式提供了相同的原子性优势。

英文原文

Data Migrations Don’t Have to Come with Downtime


2020-03-04 12:007181
用户头像
小智 让所有人认同的文字称不上表达

发布了 410 篇内容, 共 408.8 次阅读, 收获喜欢 1986 次。

关注

评论

发布
暂无评论
发现更多内容

软件著作权市场与加密货币趋势

跑一跑

著作权

从用户体验到交易闭环的全程保障!互联网行业可观测性体系建设白皮书发布

博睿数据

阿里兵临城下,美团迎来至暗时刻?

Alter

从指标异常到细节溯源:嘉为蓝鲸CMeas研发效能洞察平台链接跳转让研发数据问题可视化

嘉为蓝鲸

DevOps 研发效能 研发效能度量 研发效能管理 研发效能洞察平台

云行 | 国云聚智 AI甬动,天翼云中国行·宁波站成功举办!

天翼云开发者社区

云计算 天翼云

flywa报错java.sql.SQLSyntaxErrorException: Unknown database ‘flyway‘

刘大猫

人工智能 机器学习 算法 大模型 视觉可视化

开发效率翻倍!编码助手+云效 AI 评审如何破解代码质量与速度难题?

阿里巴巴云原生

阿里云 云原生 通义灵码

炸裂:SpringAI新版发布,终于支持断线重连了!

王磊

大模型入门攻略:定义、能力&应用场景、大模型AI工具汇总

职场工具箱

人工智能 AI大模型 大模型 agent AIGC

OpenTiny NEXT 实操体验 | 四步将你的 Web 应用升级为智能应用

OpenTiny社区

开源 前端 智能 OpenTiny

腾讯会议上线AI托管功能,元宝替你参会听会

极客天地

低代码:那些你不知道的隐藏功能大揭秘

伤感汤姆布利柏

直播预告 | 从数据孤岛到全景洞察,如何构建互联网企业可观测体系?

博睿数据

一站式数据集成:iPaaS 如何让开发者和业务人员都满意?

谷云科技RestCloud

数字化转型 数据处理 集成平台 ipaas

AI+行动号角吹响,联想智能体凭什么领跑?

脑极体

AI

收到请回答!这是一场蓄谋已久的「奔现」

CodeBuddy

TCL与火山引擎开展合作,基于豆包大模型升级电视全能交互体验

新消费日报

轻松上手 qData 数据中台开源版:Docker Compose 助你10分钟跑起来

千桐科技

大数据平台 qData 开源数据中台 Java数据中台 千数平台

使用源代码本地启动qData数据中台开源版 —— 开发者快速上手指南

千桐科技

大数据平台 qData 开源数据中台 千数平台 数据治理平台

开发效率翻倍!编码助手+云效 AI 评审如何破解代码质量与速度难题?

阿里云云效

阿里云 云原生 通义灵码

从MySQL到StarRocks:全量与增量同步的最佳实践

谷云科技RestCloud

MySQL ETL StarRocks 数据集成工具 数据库同步

基于YOLOv8的反光衣服检测识别项目|完整源码数据集+PyQt5界面+完整训练流程+开箱即用!

申公豹

人工智能

“翼”展锋芒,天翼云高性能计算领域论文被IEEE HPCC 2025收录!

天翼云开发者社区

云计算 高性能网络 天翼云

AI Compass前沿速览:CodeBuddy Code、即梦4.0、MiniCPM 4.1 、Hunyuan2.1、Qwen3-ASR、SpikingBrain脑脉冲大模型

汀丶人工智能

嘉为蓝鲸制品库:100%兼容JFrog功能,数据安全+国产化认证双重保障落地

嘉为蓝鲸

DevOps 研发效能 制品库 制品管理 JFrog迁移

稳定支撑大规模模型调用,携程旅游的 AI 网关实践

阿里巴巴云原生

阿里云 云原生 Higress

利用MailSniper测试G Suite的渗透实战

qife122

渗透测试 红队工具

嘉为蓝鲸WeOps一体化智能运维平台上新:移动端知识库随手查,AI精准检测非常规监控问题

嘉为蓝鲸

智能运维 weops 一体化运维 一体化智能运维平台 一体化运维平台

Databend 八月月报:向量检索重磅上线,性能飞跃几十倍

Databend

豆包・图像创作模型 Seedream 4.0 正式发布!

火山引擎开发者社区

火山引擎 豆包AI

HarmonyOS 5.1手势事件详解

威哥爱编程

HarmonyOS NEXT Harmony5

Nextdoor零停机Redis迁移实践_架构_Sameer Suresh_InfoQ精选文章