如果你曾参与开发过一个仅因几千用户访问就变慢的 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 也能应用他们的经验:
除非必要,否则不要拆分系统。复杂性代价高昂。
保持业务逻辑清晰,并与 I/O 解耦。
Pods、分片或领域——无论采用何种方式,都要限制故障波及范围。
实时数据支持更快的反馈和更清晰的数据管道。
降级非核心功能,保护核心功能。
最好的架构是那种让人觉得平淡无奇的架构。
最后的思考
Shopify 的故事无关炒作或流行词。
它关乎的是清晰性、工艺精神以及在规模下的从容。
他们证明了,一个设计良好的单体架构,在六边形架构和严格的模块化指导下,即使是在互联网规模下,其性能也能超越一团乱麻的微服务网络。
当你的平台每分钟推送20 TB 数据,而全世界都在不停购物时,简单并非坏事,而是卓越的体现。
总结图:Shopify 的六边形单体架构
这就是 Shopify——一个每分钟处理数 TB 数据、维持数百万企业运营的六边形单体架构,它证明了简洁性可以扩展。
如果字段的最大可能长度超过255字节,那么长度值可能…
只能说作者太用心了,优秀
感谢详解
一般干个7-8年(即30岁左右),能做到年入40w-50w;有…
230721