凌晨三点,你刚睡着。手机突然震动——支付系统告警,某数据库分片故障。你盯着屏幕,脑子里只有一个问题:现在迁移数据,要停服多久?
Stripe的工程师Jimmy Morzaria在QCon旧金山给出了一个反直觉的答案:零。不是"几乎零",不是"用户无感知",是字面意义上的零停机。他们的支付系统扛着500万QPS,可靠性达到5个9(99.999%),却能在用户刷卡的同时,把整个数据库搬走。
机场扩建的启示
Morzaria先讲了个看似无关的故事。亚特兰大机场连续24年稳居全球客运量第一,每天起降1700架航班。去年他们干了件疯狂的事:扩建使用了近50年的D航站楼——把宽度从60英尺拉到99英尺,长度增加288英尺。
约束条件是:不能关航站楼。航空公司要赚钱,乘客要登机,施工队要在旁边拆墙砌砖。他们的解法是:在远处预制700吨的模块化建筑,再用自行式模块运输车横向平移1英里,精准对接。
「这和我们的数据库迁移一模一样。」Morzaria说。Stripe的DocDB(文档数据库)面临的困境是:数据量在涨,查询模式在变,硬件会老化,但支付不能停。每一笔交易背后是一连串的余额校验、风控判定、资金划转——强一致性(strict consistency)是底线,不是可选项。
DocDB的底层设计
Stripe没有直接用现成的MongoDB或Cassandra,而是自研了一套文档数据库。核心逻辑很朴素:把数据按租户(tenant)分片,但允许跨分片的原子操作。这意味着一个用户的钱包余额和交易记录可能物理上存储在不同节点,但扣款和记账必须同时成功或同时失败。
这种设计让水平扩展(horizontal sharding)变成刚需。当单个分片的QPS或存储逼近上限,你得把数据切开,搬到新节点。传统做法是:锁表→导出→导入→切换——停机窗口从分钟到小时不等。对于Stripe,这意味着全球商户的收款中断。
Morzaria团队的做法是逻辑复制层。他们在源集群和目标集群之间搭了一座桥:写操作先记日志,异步回放;读操作根据迁移阶段智能路由。关键是状态机——每个分片处于"源端服务""双写验证""切换中""目标端服务"四种状态之一,状态转换由协调器控制,可回滚。
零停机的三重场景
Morzaria分享了三个真实用例。
第一,水平分片。某租户数据膨胀,需要拆成两个分片。迁移过程中,新写入同时落到源和目标,读请求根据键范围路由。验证阶段比对校验和,差异率低于阈值才切换。全程支付接口响应时间P99波动控制在5%以内。
第二,版本升级。数据库引擎的大版本迭代往往涉及存储格式变更。Stripe的做法是:用新版本部署一套空集群,逻辑复制追平数据,灰度切流。旧集群作为热备保留72小时,发现问题秒级回切。
第三,多租户迁移。这是最复杂的场景——把租户A从物理集群X搬到集群Y,同时租户B留在原地。需要保证跨租户的聚合查询(比如平台级风控统计)结果一致。他们的解法是:迁移期间,这类查询走联邦层,实时合并源和目标的结果集,去重后返回。
「最难的不是技术,是操作纪律。」Morzaria强调。每次迁移前必须跑通自动化测试矩阵,包括模拟网络分区、磁盘慢IO、时钟漂移。生产环境的每一次状态转换都有审计日志,可追溯到具体工程师和工单。
从5个9到"无感"的代价
5.5个9的可靠性意味着什么?年均停机时间不超过2.6分钟。Stripe把这个指标拆解到每个子系统:网络层、存储层、复制层、协调层。DocDB的零停机迁移平台本身也要满足同样的SLA。
Morzaria没有透露具体代码量,但提到一个细节:复制层的冲突解决模块经历了17次重大重构。早期版本依赖时间戳排序,在跨数据中心场景下出现因果反转;后来改用向量时钟,又带来存储开销问题;最终方案是混合逻辑时钟(Hybrid Logical Clock),兼顾性能和正确性。
这套系统支撑了什么?Stripe年处理支付额以万亿美元计。每一笔背后可能触发多次DocDB查询——余额检查、交易创建、状态更新。500万QPS不是峰值,是日常水位。
热门跟贴