Shopify 如何利用单体架构每分钟处理 30TB 数据?

B站影视 日本电影 2025-11-17 18:01 1

摘要:如果你曾参与开发过一个仅因几千用户访问就变慢的 Web 应用,那么试着想象一下一个用户量达到数十亿人时会是什么样子。

如果你曾参与开发过一个仅因几千用户访问就变慢的 Web 应用,那么试着想象一下一个用户量达到数十亿人时会是什么样子。

现在再想象一下,它实现这一切并非依靠数百个微服务,也并非依靠每年一次的前沿技术重写,而是仅仅依靠一个设计巧妙、纪律严明、架构优美的单体架构

这是一个真实的故事,讲述 Shopify 如何每分钟处理超过 20 TB 的数据,如何运营着全球最大的电子商务平台之一,同时仍能保持其架构的简洁、可扩展且出人意料地人性化。

黑色星期五

对大多数公司而言,黑色星期五是压力巨大的。

对 Shopify 呢?这是传奇性的时刻。

当午夜钟声敲响时,来自世界各地的流量如洪水般涌入。

数以百万计的人们同时打开由 Shopify 驱动的商店,如 Gymshark、Kylie Cosmetics 和 Allbirds。

在 2021 年的黑色星期五周末期间:

Shopify 每分钟处理30 TB 的数据他们的服务器每分钟承受超过 3200 万次请求每秒处理1100 万次 MySQL 查询每分钟产生超过 390 万美元的销售额

而且,系统没有崩溃。

没有中断。

没有不眠之夜。

只有平稳的扩展。

那么,秘诀是什么?

成长起来的单体架构

Shopify 的架构围绕一个模块化单体构建——这是一个主要用 Ruby on Rails 编写的单一代码库,但被精心地构建成具有逻辑边界

与将所有东西拆分成细小的微服务(每个微服务都有自己的基础设施、部署流程和复杂性)不同,Shopify 将其单体架构视为一个由街区组成的城市——一个城市,多个区域。

每个"区域"或组件负责一个业务领域:

结账支付订单管理后台库存分析

简单视图:

每个模块都拥有:

自己的数据所有权自己的公共 API自己的维护团队

它们在同一代码库内相互隔离——这意味着更少的部署麻烦和更紧密的集成。

Shopify 使用一个名为 Packwerk 的内部工具来强制执行这种纪律。

它能自动检测到一个模块何时访问了它不该访问的其他模块。

这就是为什么一个拥有 10 多年历史、由数千名工程师维护的单体架构,至今仍能保持清晰和模块化。

引入六边形架构

如果说模块化决定了什么功能位于何处,那么六边形架构则决定了这些部件如何与外部世界通信。

六边形架构也被称为端口与适配器模式,它让 Shopify 能够将其核心逻辑与外部混乱(如 API、数据库或队列)独立开来。

核心思想如下:

应用程序是一个六边形——中心(业务逻辑)永不改变,而边缘(适配器)负责处理与外部世界的通信。

在 Shopify 世界中的运作方式

让我们以"创建订单"为例。

传统方法(紧耦合):

控制器直接调用数据库业务逻辑存在于控制器内部对 API 的任何更改都会破坏一切

六边形方法(Shopify 的方式):

────────────────────────┐│ Web Layer ││ (GraphQL, REST, Mobile APIs, etc.) │└──────────────────┬───────────────────┘│▼┌────────────────────────────┐│ Application Service ││ (CreateOrderUseCase Port) │└────────────┬───────────────┘│(via Interface)│┌────────────────────────────┐│ Adapters ││ (MySQL, Kafka, Redis etc.) │└────────────────────────────┘

当客户点击"结账"时,流程如下:

API 适配器接收到请求将其传递给核心用例——CreateOrderUseCase该用例运行领域逻辑:库存检查、支付验证、折扣规则等适配器层将结果持久化到 MySQL 或向 Kafka 队列发送消息

关键点在于?

核心逻辑从不知晓也无需关心数据是来自 GraphQL、REST 还是一个 CLI 任务。

这种隔离意味着 Shopify 可以在不触及业务逻辑的情况下,演进技术——更换队列、重构 API 或切换数据库。

Pods

单体架构的水平扩展

当你运营着一个托管数百万商店的平台时,一次病毒式的产品发布就可能拖垮整个平台。

Shopify 通过 Pods 优雅地解决了这个问题——即单体架构的隔离集群。

每个 Pod 就像一个小型的 Shopify:

独立的数据库分片独立的缓存独立的任务队列独立的工作进程

所有请求都通过一个名为 Sorting Hat 的智能内部服务(是的,就像《哈利·波特》里的分院帽一样 )路由到正确的 Pod。

其结构如下所示:

因此,如果 Kylie Jenner 的新产品发布导致 Pod A 崩溃,Pod B(服务于其他 10 万家商店)甚至不会察觉到。

这就是 Shopify 在全球范围内扩展的方式,而无需碎片化成数百个微服务。

数据流

在每一次"加入购物车"点击的背后,是海量的数据流动。

Shopify 是这样处理的:

Shopify 的数据管道随着时间不断演进:

旧系统:Longboat —— 每小时复制数据的批量查询新系统:Debezium + Kafka —— 实时变更数据捕获

现在,每一个数据库变更——一个新订单、退款或更新——都会实时流入 Kafka。

这使得在 PB 级的数据上实现实时仪表板、即时欺诈检测实时分析成为可能。

优雅应对流量峰值

当 100 万人在同一秒点击"加入购物车"时,你不能依赖蛮力。

Shopify 依赖的是精巧的缓存和受控的服务降级。

边缘缓存(CDN): 直接提供静态页面和媒体资源。Redis/Memcached: 处理会话、预计算数据和快速读取。后台队列: 卸载高成本任务(电子邮件、Webhooks、分析)。优雅降级: 在流量峰值期间,非核心功能自动暂停。

例如:如果在某位名人产品发布期间流量激增 100 倍,推荐功能可能会暂停,但结账功能绝不会中断。

可预测性胜过临时救急。

坚持使用 MySQL

Shopify 仍然使用 MySQL 作为其核心数据库。

但他们将其扩展到了地球上少有的规模。

数百个分片分布在各个 Pod 中每秒超过 1000 万次查询跨副本的自动负载均衡基于快照的备份,恢复窗口为 30 分钟在线模式变更,实现零停机时间

他们甚至编写了内部系统,以动态地在分片间重新平衡商店,从而避免任何单一数据库成为热点。

这不是什么炫酷的技术。

这是枯燥的卓越。

黑色星期五值班是怎样的体验

一位工程师曾说:

"你为战斗做好准备。你预想着警报会响。你想象着混乱。但当流量来袭时——图表曲线飙升,Pods 嗡嗡作响,缓存正常工作,然后……什么也没崩溃。你只是小口喝着咖啡,微笑着。"

这就是大规模下简洁架构的魔力。

当一切都在平稳运转时,一年中最繁忙的一天也会显得很平静。

我们都能借鉴的经验教训

你不需要运营 Shopify 也能应用他们的经验:

1、从单体开始,向模块化发展

除非必要,否则不要拆分系统。复杂性代价高昂。

2、遵循六边形架构原则

保持业务逻辑清晰,并与 I/O 解耦。

3、隔离故障

Pods、分片或领域——无论采用何种方式,都要限制故障波及范围。

4、采用流式处理,而非批量处理

实时数据支持更快的反馈和更清晰的数据管道。

5、故障做好优雅降级计划

降级非核心功能,保护核心功能。

6、让'枯燥'变得美好

最好的架构是那种让人觉得平淡无奇的架构。

最后的思考

Shopify 的故事无关炒作或流行词。

它关乎的是清晰性、工艺精神以及在规模下的从容。

他们证明了,一个设计良好的单体架构,在六边形架构严格的模块化指导下,即使是在互联网规模下,其性能也能超越一团乱麻的微服务网络。

当你的平台每分钟推送20 TB 数据,而全世界都在不停购物时,简单并非坏事,而是卓越的体现。

总结图:Shopify 的六边形单体架构

这就是 Shopify——一个每分钟处理数 TB 数据、维持数百万企业运营的六边形单体架构,它证明了简洁性可以扩展。

作者丨Himanshu Singour 编译丨Rio

来源丨网址:https://medium.com/@himanshusingour7/how-shopify-handles-30tb-of-data-every-minute-with-a-monolithic-architecture-cad54df86955

dbaplus社群欢迎广大技术人员投稿,投稿邮箱:editor@dbaplus.cn

来源:dbaplus社群一点号

相关推荐