金融级可靠性:两地三中心、单元化、RPO/RTO、灰度
如果说前面二十几篇讲的是”钱怎么正确地流动”,那这一篇讲的是”在机房着火、光缆被挖断、数据库脑裂、监管强制演练的时候,钱还能不能正确地流动”。
金融系统的可用性有一个其他行业很少遇到的性质:它不是一条业务指标,而是一条合规指标。电商大促宕机半小时,损失是营收 + 品牌;核心账务系统宕机半小时,损失是营收 + 品牌 + 一张央行罚单 + 一次年度报告里的重大事项披露 + 可能的行长约谈。所以,金融级可靠性的工程决策,几乎每一步都同时挂着两根弦:一根是”怎么让系统不挂”,一根是”挂了之后怎么向监管解释”。
这篇文章面向以下三类读者:
- 在股份制银行、城商行、券商、支付机构的科技部门,正在或即将牵头一次同城双活 / 异地多活 / 单元化改造的架构师;
- 互联网金融公司(支付、数字银行、财富管理)中接管了稳定性(SRE)岗位,需要对齐银保监与人行监管要求的工程师;
- 交易所、清算所、CBDC 等基础设施背景的从业者,想看看商业银行与互联网金融在可靠性上的差异。
我们不会把全部法规条文抄一遍——法规的细节每年都在变,但它们落到架构上的约束是稳定的:RTO 秒级到分钟级、RPO 接近零、六级灾备、年度演练、关键岗位双人值守、重大故障 2 小时内上报。我们围绕这些稳定约束展开。
一、监管基线:从 RTO/RPO 到六级灾备
1.1 RTO、RPO、MTPD、WRT:四个被混用的概念
金融圈写稳定性方案时,RTO 与 RPO 几乎永远成对出现,但它们常被误用。先把四个术语拧清楚:
- RTO(Recovery Time Objective,恢复时间目标):灾难发生到业务恢复对外服务之间允许的最长时间。衡量的是”多久能再开门”。
- RPO(Recovery Point Objective,恢复点目标):灾难发生时允许丢失的数据时间窗口。衡量的是”丢多少笔”。RPO = 0 意味着一笔都不能丢。
- MTPD(Maximum Tolerable Period of Disruption,最大可容忍中断时间):业务方能接受的上限,通常 > RTO,是合规谈判时给出的”红线”。
- WRT(Work Recovery Time,工作恢复时间):从技术恢复到业务数据追平、可以重新对外开放的时间。RTO = 系统恢复时间 + WRT。
一个常见的误区:只写”RTO 30 秒”,不写 WRT。数据库 30 秒内起来了,但账务要回放两小时增量才能对外——那对业务来说还是中断了两个多小时。在做需求澄清时,务必和业务、合规一起确认 MTPD、RTO、RPO、WRT 四个数字,否则方案必翻车。
1.2 中国人民银行与银保监的可用性基线
中国金融业的可用性监管是分层的:
- 人民银行负责支付清算基础设施的连续性要求,覆盖 CNAPS、CIPS、网联、银联以及接入它们的成员机构;
- 国家金融监督管理总局(原银保监会)主管银行业、保险业机构的信息科技风险与外包风险管理;
- 证监会主管证券期货行业信息系统。
贴近架构决策、至今仍被反复引用的文件有:
- 《商业银行数据中心监管指引》(银监办发〔2010〕114 号):确立了商业银行数据中心的基本能力要求,推动同城与异地灾备建设;
- 《银行业金融机构信息科技外包风险管理指引》(原银监发〔2013〕5 号,后续修订):明确了对云服务、灾备服务外包的风险管理边界,强调”数据不出境”“可审计”“可替换”;
- 《银行业金融机构信息系统重要性评估与定级指引》:把系统按重要性分为一般、重要、核心三档,不同档位对应不同的 RTO/RPO 要求;
- 《金融行业网络安全等级保护实施指引》(JR/T 0071):三级、四级等保对应的容灾要求;
- 《证券期货业信息系统运维管理规范》(JR/T 0060):证券交易、登记结算、基金托管等系统的运维底线。
落到数字上,行业里较常被引用的核心系统基线(各机构内部口径略有差异,以最终监管函件为准):
| 系统类别 | 典型 RTO | 典型 RPO |
|---|---|---|
| 核心账务、支付清算(重要系统) | 分钟级(通常 ≤ 30 min) | 0 或接近 0 |
| 关键联机业务(手机银行、网银) | 30 min ~ 2 h | ≤ 15 min |
| 一般管理类、数仓类 | 4 h ~ 24 h | ≤ 1 h |
| 监管报送、离线分析 | 24 h | 当日可重算 |
核心系统 RPO 接近 0,意味着单纯的异步日志传输不够,必须走同步复制或分布式一致性协议(Paxos/Raft)——这决定了你不可能靠”主备 + MySQL 异步 binlog”蒙混过关。
1.3 GB/T 20988:灾难恢复六级
GB/T 20988-2007《信息系统灾难恢复规范》 是国内灾备能力分级的事实标准,把灾备能力分为六级:
| 级别 | 关键特征 | 典型 RTO | 典型 RPO |
|---|---|---|---|
| 第 1 级:基本支持 | 介质异地存放 | 数天 | 1 天 ~ 1 周 |
| 第 2 级:备用场地支持 | 有冷备场地、无设备 | 1 ~ 7 天 | 1 ~ 7 天 |
| 第 3 级:电子传输和部分设备支持 | 异地存储 + 部分设备 | 1 ~ 3 天 | 数小时 ~ 1 天 |
| 第 4 级:电子传输及完整设备支持 | 完整温备、定期切换演练 | 数小时 ~ 2 天 | 数小时 |
| 第 5 级:实时数据传输及完整设备支持 | 热备、准实时同步 | 数分钟 ~ 数小时 | 分钟级 |
| 第 6 级:数据零丢失和远程集群支持 | 双活 / 多活、同步复制 | 分钟级 | 0 |
商业银行核心账务、支付清算、券商交易系统要求达到第 5 级或第 6 级;银行渠道类、保险核心等系统普遍第 4 ~ 5 级。第 6 级不是”架构更高级”这么简单,它意味着同步复制链路上任何一个网络抖动都会直接反映到业务 RT 上——工程上能做到第 6 级的组织,运维能力与第 4 级是完全不同的量级。
1.4 美国与欧洲的参照线
跨境机构与出海团队还要看一圈国际监管:
- SOX(Sarbanes-Oxley Act):Section 404 要求上市公司对财务报告相关内部控制(含信息系统)进行年度评估。银行业在 ITGC(IT General Controls)下对变更管理、访问控制、业务连续性有具体审计要求。
- FFIEC Business Continuity Management Handbook:美国联邦金融机构检查委员会发布的 BCP/DR 指南,覆盖影响分析、RTO/RPO、演练、第三方依赖。
- OCC Heightened Standards、FRB SR 11-7(模型风险)、SR 20-24(IT 风险管理):对联邦注册银行进一步细化。
- 欧盟 DORA(Digital Operational Resilience Act):2025 年起全面适用,要求金融机构对 ICT 风险实施分类管理、事件上报、威胁情报、渗透测试(TLPT)、第三方集中度风险治理。DORA 的一个重要工程影响是:关键第三方云服务商 直接被纳入欧洲监管范围。
一个典型的工程约束是:SOX + DORA 叠加下,跨国金融机构用同一套云供应商跑所有地区的核心系统,正在变得越来越难。这会反过来推动”多云 + 多活”架构。
1.5 监管对”云”的额外态度
2020 年以后,人行、金融监管总局对金融云的规则逐步细化。几个对架构有直接影响的口径:
- 数据本地化:境内用户的金融数据原则上不出境。跨境支付等特定场景有例外,但需专门备案。
- 重要系统不得依赖单一外部服务商:监管倾向于看到”双云 / 多云 / 私有云 + 公有云”的组合。
- 关键岗位 / 关键操作自主可控:核心数据库、核心应用的运维人员须在行内;禁止将 root 权限交给外包。
- 可审计:所有变更、所有数据访问需有审计日志,可随监管调阅。审计日志本身也要异地存储、不可篡改。
这些要求与工程上”为什么要自建配置中心、为什么必须有审计链路、为什么要有多云容灾”直接对上。
二、可用性指标:SLA、SLO、SLI、故障预算
工程 side 与合规 side 常常讲的不是一种”可用性”。合规口径通常以年度统计为准(如 99.99% / 年),工程口径则以滚动 28 天或季度统计。下面先把几个术语定义清楚:
- SLA(Service Level Agreement,服务级别协议):对外承诺,违约要赔;常写在合同里。
- SLO(Service Level Objective,服务级别目标):对内目标,通常严于 SLA,用来驱动工程改进。
- SLI(Service Level Indicator,服务级别指标):实际测量指标,可用性、延迟、错误率等。
几个 9 对应的允许中断时间如下:
| 可用性 | 年允许中断 | 月允许中断 | 周允许中断 |
|---|---|---|---|
| 99%(两个 9) | 3.65 天 | 7.2 小时 | 1.68 小时 |
| 99.9%(三个 9) | 8.76 小时 | 43.2 分钟 | 10.1 分钟 |
| 99.95% | 4.38 小时 | 21.6 分钟 | 5.04 分钟 |
| 99.99%(四个 9) | 52.56 分钟 | 4.32 分钟 | 1.01 分钟 |
| 99.999%(五个 9) | 5.26 分钟 | 25.9 秒 | 6.05 秒 |
几个在金融场景里容易被忽视的细节:
- 可用性不是简单时间相除。支付、交易类系统一般要区分”业务可用性”(成功率)与”服务可用性”(存活率)。一个撮合引擎 99.99% 在线但成交成功率 90%,对业务是失败的。
- 长尾延迟要进 SLI。支付链路 P99 从 200 ms 涨到 3 s,在上游侧表现就是超时批量重试,一堆重复扣款风险。SLI 里至少要有 P95、P99、P999。
- 故障预算(Error Budget):SLO 99.99% 对应每月 4.32 分钟预算。当月已经用掉一半,就要冻结非必要发布、把资源压到稳定性治理。这在银行更多叫”变更冻结期”,在互联网金融叫”封网”。
- 外部依赖的 SLA 组合。你的支付成功率上限 = 下游清算通道 × 发卡行 × 路由 × 自身服务。四环 99.99% 乘起来约 99.96%。不要给自己签 SLA 超过输入组合的理论上限。
三、架构演进:从单机到多单元
3.1 六个阶段
金融系统的高可用架构在过去二十年走过一条比较清晰的阶梯:
flowchart LR
A[单机] --> B[主备]
B --> C[同城双活]
C --> D[两地三中心]
D --> E[三地五中心]
E --> F[多单元 LDC]
- 单机:早期柜面、PC 端网银时代,数据库、应用、文件系统在一台机器上,靠备份磁带做灾备。2000 年代早期的城商行普遍如此。
- 主备:数据库主从复制 + 冷备机房,RPO 小时级。能应付单机房硬件故障,不能应付机房级灾难。
- 同城双活:两个机房距离小于 30 ~ 50 km,通过 DWDM 专线连通,RTT 在 1 ~ 2 ms 内,数据库同步复制。典型实现:Oracle RAC Extended + 存储复制(SRDF/GoldenGate)、OceanBase 同城三副本。
- 两地三中心:在同城双活基础上再加一个异地灾备中心,应付城市级灾难(大地震、大停电、广域网级光缆中断)。异地机房与主站距离 > 500 km,通常走异步复制,RPO 秒到分钟级。
- 三地五中心:蚂蚁首创并公开提出的架构:三个城市、每个城市 1 ~ 2 个机房,Paxos 五副本多数派。理论上任一城市完全宕掉,系统仍可写。
- 多单元(LDC / Set):把用户按某种规则切成 N 个”单元”,每个单元内部是完整的业务闭环(应用 + 数据库 + 缓存 + 消息),跨单元走路由网关。单元化是今天互联网金融公司的主流形态。
3.2 每一阶段解决的问题 vs 新引入的复杂度
| 阶段 | 解决的问题 | 新引入的复杂度 |
|---|---|---|
| 主备 | 硬件单点 | 主备切换数据一致性 |
| 同城双活 | 机房级故障 | 双写冲突、脑裂、仲裁 |
| 两地三中心 | 城市级灾难 | 异步复制的 RPO > 0、切异地需长时间决策 |
| 三地五中心 | 异地切换时间过长 | 跨地域 Paxos 的延迟敏感性、成本 3x |
| 多单元 | 单库容量上限、爆炸半径 | 路由、跨单元事务、全局数据、部署复杂度 |
经验上:不要跳级。一个还在做主备切换演练失败三次的团队,直接上三地五中心只会把故障率放大。金融系统演进的可靠性比单次架构纯度更重要。
四、两地三中心:工程细节
两地三中心(2R3DC)是目前中国商业银行核心系统的主流形态。很多行看起来已经”异地多活”,剥开来看仍是两地三中心 + 一些冷门业务在异地的容灾演练。下面拆开看。
4.1 典型拓扑
flowchart TB
subgraph CityA[城市 A 主站]
direction LR
A1[生产机房 A1<br/>应用 + 主库]
A2[同城灾备 A2<br/>应用 + 同步副本]
end
subgraph CityB[城市 B 异地]
B1[异地灾备 B1<br/>应用 + 异步副本]
end
A1 <-- 同步复制 --> A2
A1 -- 异步复制 --> B1
A2 -. 异步复制 .-> B1
LB[GTM/F5/GSLB] --> A1
LB --> A2
- A1 与 A2:同城,DWDM 专线,距离 < 50 km,RTT < 2 ms,做同步复制。业务可以真双活(读写都分到两边)也可以主备(只读分流)。
- A1 到 B1:异地异步复制。正常时 B1 只做容灾保留与只读,不承担生产流量。
- 灾难切换:A1 机房整体失守,GTM 把流量切到 A2;A 城市整体失守(大地震、大洪水),才切到 B1。A→B 切换是一次重大管理决策,不是技术决策。
4.2 同城双活的三种实现
- 存储级同步复制:EMC SRDF、华为 HyperMetro。应用无感知,但一致性依赖存储;存储链路故障时容易脑裂。多见于传统核心账务。
- 数据库级同步复制:Oracle Data Guard MaxAvailability、DB2 HADR、PostgreSQL synchronous_commit=on、OceanBase 三副本 Paxos。更灵活,RPO=0 更可靠。
- 应用级双写:应用同时写两个库,通过消息或对账保证一致性。灵活但容易写错,一般只用于边缘业务。
选型判断:如果你的核心账务 DB 是 Oracle / DB2,短期走存储复制或 Data Guard;如果你在做国产化替换,直接上 OceanBase / GaussDB / TDSQL 这类内置 Paxos/Raft 的数据库。
4.3 异地灾备的常见坑
- 演练时切得回,出事时切不回:因为演练时异地副本是冷的,生产流量切过去压力不匹配,数据库连接池、JVM、缓存全是冷的。经验:每季度演练一次真实切流至少 1 小时。
- 配置漂移:A1 做过的参数调整没同步到 B1,切过去立刻崩。应对:所有配置通过配置中心下发,禁止登录生产机器改参数。
- 监管批文的时间成本:异地切换往往需要董事长 / 行长批准、监管备案。技术准备好 1 分钟,管理链路 4 小时是常态。这就是为什么异地切换 RTO 是”按小时算”的。
五、单元化(Set / LDC)
单元化是互联网金融公司突破”单机数据库容量上限”与”爆炸半径”两个问题的共同答案。蚂蚁集团称之为 LDC(Logical Data Center),阿里集团称之为 单元化,腾讯称之为 Set,字节称之为 单元。名字不同,骨架相似。
5.1 核心思想
把用户按某个维度(通常是 user_id 哈希)切成 N 个逻辑单元,每个单元内部拥有完整的业务处理链路与独立的数据库、缓存、消息队列。单元之间:
- 独立:一个单元炸了,只影响 1/N 用户;
- 同构:每个单元跑相同的代码、相同的 schema;
- 可路由:入口网关根据用户 ID 路由到对应单元;
- 可迁移:单元的用户集合可以动态迁移(灰度、扩容、故障切流)。
5.2 三种 Zone:GZone / RZone / CZone
以蚂蚁公开披露的架构为参考(并非实现细节):
- RZone(Region Zone):真正的单元,放可分片业务数据(账户、交易),按用户 ID 分片。每个 RZone 一套独立数据库。
- GZone(Global Zone):全局共享数据,如配置、币种、商户元信息。通常全局只有一主多从。
- CZone(City Zone):同城共享的只读数据,由 GZone 异步同步而来,给 RZone 本地高速访问。降低 RZone 跨城读 GZone 的延迟。
flowchart TB
subgraph CityA[城市 A]
subgraph RA1[RZone A1]
APPA1[应用] --> DBA1[(分片 1-25 DB)]
end
subgraph RA2[RZone A2]
APPA2[应用] --> DBA2[(分片 26-50 DB)]
end
CZA[(CZone A<br/>同城只读副本)]
end
subgraph CityB[城市 B]
subgraph RB1[RZone B1]
APPB1[应用] --> DBB1[(分片 51-75 DB)]
end
subgraph RB2[RZone B2]
APPB2[应用] --> DBB2[(分片 76-100 DB)]
end
CZB[(CZone B)]
end
GZ[(GZone<br/>全局主库)]
GZ -. 异步 .-> CZA
GZ -. 异步 .-> CZB
5.3 分片键的选择
金融场景里分片键不是一个纯技术问题,它直接决定:
- 跨单元事务比例:分片键越贴近业务主体(用户 / 商户 / 账户),跨单元事务越少;
- 热点分布:双 11 下单、春节抢红包时,分片键分布不均会制造”热点单元”;
- 运营视角:是否支持按地区做差异化(比如上海商户流量全在 RZone A)。
常见选型:
| 业务 | 分片键 | 原因 |
|---|---|---|
| C 端支付 | user_id | 大多数交易是单用户行为 |
| B 端收单 | merchant_id | 商户是主单,商户清算、对账、账单天然按商户聚合 |
| 理财 / 基金 | user_id | 同上;基金产品放 GZone |
| 跨机构转账 | 付款方 user_id | 收款方需跨单元路由 |
| 证券交易 | account_id | 交易账户 |
经验法则:选一个能让 80%+ 事务落在单个分片内的键;剩下 20% 用”跨单元事务”兜底。
5.4 单元化的跨单元事务
用户 A 在 RZone 1,用户 B 在 RZone 2,A 给 B 转账:
- 两阶段提交(2PC) 在金融场景几乎不用,跨机房长事务、锁持有时间长、性能差;
- TCC / SAGA:把转账拆成 Try-Commit-Cancel 或补偿链。参见本系列 《幂等、事务与一致性》;
- 消息最终一致:落一条事务消息,异步送到目标单元处理;
- 全局服务路由:金额 + 凭证放 GZone,收付款账户分别在两个 RZone 异步入账。
真实系统通常是以 SAGA / 消息为主 + 对账兜底。对账系统(第 23 篇)的意义在这里被进一步放大。
5.5 单元切流:从 1% 到 100%
单元化真正的威力在流量编排。几个常用动作:
- 灰度发布:新版本先放一个 RZone,24 小时观察,再全量;
- 染色压测:对染色流量(加特殊 header)把消息路由到影子库,不影响真实用户;
- 故障切流:RZone 1 数据库抖动,把 RZone 1 的分片范围临时路由到 RZone 2 的副本(前提是副本是同步复制);
- 容量腾挪:双 11 前把一些低峰城市的 RZone 合并,腾出资源给主力 RZone。
切流有一个关键约束:一个分片在任何时刻只能在一个单元写入。即”一写多读”,否则立刻产生写冲突。后面的流量切换代码示例会展示如何以”分片号为单位”做写入归属切换。
5.6 切流的时序
一次典型的分片级切流时序如下:
sequenceDiagram
participant OP as 值班工程师
participant CMD as 应急平台
participant CFG as 配置中心
participant GW1 as 网关集群 A
participant GW2 as 网关集群 B
participant SRC as 源单元 RZ-A1
participant DST as 目的单元 RZ-A2
OP->>CMD: 选择"分片 0-49 切至 RZ-A2"
CMD->>CMD: 审批(双人复核)
CMD->>SRC: 冻结分片 0-49 新写入(只读)
SRC-->>CMD: 冻结 ACK
CMD->>DST: 拉起分片 0-49 Leader
DST-->>CMD: 副本一致性校验通过
CMD->>CFG: 推送新路由规则
CFG-->>GW1: 广播
CFG-->>GW2: 广播
GW1->>DST: 新请求路由到 RZ-A2
GW2->>DST: 新请求路由到 RZ-A2
CMD->>OP: 切流完成、展示成功率
几个关键细节:
- 先冻结再拉起:源单元必须先冻结写入,避免双写;
- 副本一致性校验:目的单元的副本必须追平,才允许承担写入;
- 原子广播:配置中心向所有网关同时推送,最坏情况下也必须在秒级完成;
- 回滚按钮:整个过程任一步骤可以回滚到切流前状态。
六、异地多活的数据同步与冲突
6.1 常用数据同步管道
| 工具 | 场景 | 特征 |
|---|---|---|
| Oracle GoldenGate(OGG) | Oracle/异构迁移 | 金融系统的老牌工具,稳定但昂贵;日志级复制 |
| 阿里 DRC(Data Replication Center) | 阿里系自用 | 毫秒级延迟、可做双向复制、支持单元化 |
| Canal / Debezium | MySQL/PostgreSQL | 开源,增量 CDC,常搭 Kafka |
| OceanBase OMS | OB 跨地域同步 | 与分布式事务协议耦合,原生支持 |
| GaussDB DRS | GaussDB | 华为云原生 |
| Kafka MirrorMaker 2 | 消息复制 | 跨机房消息镜像 |
选择逻辑:能原生一致性复制就别走逻辑复制,能单向就别双向。双向复制给冲突处理留的活永远比想象中多。
6.2 冲突处理的四种策略
异地多活一旦允许两地都写同一个实体,冲突就是必然。几种策略:
- 业务规避(推荐):分片键把同一用户固定到一个单元写,双向复制只用来做容灾副本,不用来做并行写入。99% 的金融场景选这个。
- 单向写,反向只读:A 写 B 读,B 写 A 读。适合”活-备”模式。
- Last Write Wins(LWW):用物理时间戳裁定,但时钟漂移会坑你。金融极少用。
- 版本向量 / CRDT:为每条记录维护 (node_id, counter) 的版本向量,合并时按语义合并。适合账单类可合并的数据,不适合余额类不可合并的数据。
金融核心账务层面,唯一被广泛接受的答案是”业务规避冲突”。所谓”异地多活”在会计意义上是”多个单元、各自写各自的分片、通过复制互为容灾”。
6.3 流量调度
调度链路是从 DNS 一路到应用的:
- DNS / GSLB / GTM:根据用户地理位置或单元归属返回不同 VIP。粒度粗、生效慢(TTL)。
- AGW / API Gateway:网关层根据 user_id 哈希决定路由到哪个单元。粒度到请求级,秒级生效。
- RPC 路由(Service Mesh):服务间调用带上 sharding_key,路由到目标单元的服务实例。
- 消息路由:事务消息带 sharding_key,落到对应单元的 topic partition。
推荐结构:DNS 粗分 + 网关精确路由。DNS 用来把用户大致引导到附近城市,网关根据业务逻辑做精确单元匹配。后面的代码示例会实现网关侧的路由规则下发与生效。
七、容灾演练与混沌工程
7.1 监管要求的演练节奏
中国银保监与人行对核心系统灾难演练有明确要求,行业普遍执行的节奏:
- 每年至少一次真实切换演练(真切流,不是桌面推演);
- 每季度一次同城切换演练;
- 重大版本变更后 30 天内做一次专项演练;
- 演练方案需报董事会 / 风险管理委员会;演练报告需保留可供检查。
很多机构的问题不是”不演练”,是”演练流程太重以至于一年只敢做一次,平时的日常切换能力退化”。这就是混沌工程进入金融行业的契机。
7.2 混沌工程的金融落地
混沌工程(Chaos Engineering)的核心假设是:与其等事故发生,不如主动注入受控故障,把系统的失败模式提前暴露。Netflix Chaos Monkey 是最早的实践,金融行业常用的工具:
- ChaosBlade(阿里开源):命令行工具,支持 CPU、IO、网络、Java 方法、Kubernetes Pod 级注入;
- Chaos Mesh(PingCAP 开源,CNCF 毕业):面向 Kubernetes 的混沌平台;
- Gremlin:商业化方案;
- 自研平台:蚂蚁 SRE 有内部”故障演练平台”,将演练流程、审批、回滚、观察一体化。
金融版的混沌工程与互联网版的差异:
| 维度 | 互联网 | 金融 |
|---|---|---|
| 注入范围 | 生产常态注入 | 受控窗口、分级审批 |
| 审批 | PR review | 风险委员会 |
| 回滚 | 自动 | 自动 + 人工双确认 |
| 记录 | 监控日志 | 额外归档,供监管抽检 |
7.3 典型故障注入场景
| 场景 | 注入方式 | 预期观察 |
|---|---|---|
| 机房网络中断 | iptables DROP + 路由黑洞 | GSLB 切换时间、会话飘移成功率 |
| 数据库主节点宕机 | kill -9 + 冻结 Paxos 选主 | 选主时间、业务 RT 抖动、TPS 掉底 |
| 缓存集群整体失效 | 清空所有节点 | DB 负载、限流生效 |
| 消息队列阻塞 | 冻结消费 | 积压告警、降级策略 |
| 磁盘只读 | mount -o remount,ro | 写失败率、切换决策是否触发 |
| 跨地域网络抖动 | tc netem delay 500ms loss 5% | 异步复制延迟、业务降级 |
| 时钟漂移 | date -s / chrony 偏差 | 幂等判重、TTL 失效 |
几个金融场景特有的注入值得专门列出:
- 支付通道熔断:模拟工行 / 招行支付通道 100% 超时,验证路由系统是否把流量切到其他通道;
- 清算文件延迟:模拟 CNAPS 文件下发延迟 4 小时,验证日终处理容忍度;
- 对账不平:模拟某个上游多发 / 少发一笔,验证对账系统与人工介入流程。
7.4 演练成熟度的五级模型
对一个金融机构的演练能力做自我评估,可以用下面的五级模型:
| 级别 | 特征 |
|---|---|
| L1:纸上 | 只写预案,不演练;事故时翻预案 |
| L2:桌面 | 桌面推演,不切真流量 |
| L3:受控演练 | 每季度一次受控时间窗切流,范围有限 |
| L4:日常演练 | 混沌平台化,每周都有小规模注入 |
| L5:生产常态 | 生产环境持续注入故障,SLI 不受影响即合格 |
大部分股份制银行在 L2 ~ L3 之间;头部互联网金融公司(蚂蚁、微众、网商等)在 L4 ~ L5。从 L3 升到 L4 的关键门槛是SLI/SLO 体系先于演练建起来——没有稳定的指标做判据,常态化注入就是制造事故。
八、金融级数据库
8.0 为什么核心账务对数据库特别挑剔
账务的 OLTP 模式有几个特征,决定了一般互联网数据库难以胜任:
- 强一致:余额类字段不能出现”最终一致”,每一笔写入必须在后续读中立刻可见;
- 长尾事务:清算批处理的单条事务可能涉及几十万行,一般互联网场景极少出现;
- 热点账户:手续费收入账户、系统过渡账户是单行热点,常见 QPS 上万;
- 跨行跨分片事务:转账涉及两个账户,分布式事务是基础能力而非可选项;
- 可追溯性:所有写入必须可回溯到分钟级、秒级的历史版本,监管审计随时查。
MySQL + 分库分表方案在前三项做得不错,第四、五项吃力。这是国产分布式数据库在 2020 年之后大规模进核心的根本原因。
8.1 国产分布式数据库的三强
| 产品 | 背景 | 一致性协议 | 典型场景 |
|---|---|---|---|
| OceanBase | 蚂蚁 | Paxos | 核心账务、支付、银行新核心 |
| GaussDB | 华为 | Paxos / Raft 变体 | 股份行 / 政企核心 |
| TDSQL | 腾讯 | Raft(TDSQL-C、TDSQL-H) | 银行分布式核心、支付 |
这三家在过去五年密集进入银行核心系统替换场景:中国工商银行、建设银行、交通银行、南京银行、张家港行等都有公开披露的国产化改造项目。
工程上,这三家产品相似的点:
- 多副本强一致:默认三副本 Paxos/Raft,多数派写入成功才 ACK;
- 水平扩展:数据分区 + 自动均衡;
- 分布式事务:原生支持 XA 或类 Percolator 两阶段,隐藏分布式事务复杂度;
- HTAP 支持:允许在同一套数据库里跑 TP 与轻量 AP,避免额外的数仓链路。
8.2 Paxos 副本的地理布局
以三地五中心为例,一个常见布局:
主 城 A:副本 1(Leader 候选)、副本 2
同 城 B:副本 3
异 地 C:副本 4、副本 5
多数派 3 个副本。读写:
- 正常:Leader 在 A,A + B 两个副本 ACK 即达多数,RT 约 2 ms;
- A 城市挂:B + C 两城继续组成多数派,异地写入 RT 增加到 20 ~ 40 ms;
- AB 两城同时挂:C 两个副本不足多数,不可写,但数据不丢。
这种布局的关键工程约束是:同步写入 RT 取决于多数派最慢的那个副本。如果三地延迟差异大,要么牺牲一部分 RT、要么把一个异地副本设为 Learner(不计入多数)。
8.3 分布式事务的代价
分布式事务在 OceanBase / TiDB / GaussDB 里普遍使用两阶段或 Percolator 变体,关键代价是:
- Prepare 锁持有时间:事务涉及多个分片时,prepare 会在每个分片持锁,期间其他事务被阻塞;
- 协调者宕机:需要事务管理器高可用 + 事务状态可恢复;
- 长事务:网络抖动让分布式事务拖长,把整个分片的并发拉低。
经验规则:核心链路能单分片事务就单分片,不能单分片就 SAGA/TCC,避免依赖分布式事务做吞吐。
九、全链路压测
9.0 为什么要”全链路”
早期银行做性能测试习惯单服务压:登录 5000 QPS、支付 3000 TPS、查询 10000 QPS。上生产一个活动,整体直接崩。原因:
- 真实链路存在依赖倍增效应:一次支付触发 8 次下游调用、3 次 MQ、2 次对账,单服务压测完全不反映链路;
- 资源争用不是线性:CPU、网络、DB 连接池、线程池是共享的,A 忙的时候 B 也会慢;
- 外部依赖:银联通道、合作方系统,只有在真实链路里才能被正确衡量。
全链路压测的立身之本是”用生产流量的真实形态、在生产系统上压、产出生产决策”。
9.1 影子库 + 染色流量
核心思路:
- 真实流量带上染色标识(header、TraceId 前缀、mq 属性);
- 应用层看到染色标记后,把数据读写重定向到”影子表”(shadow table),shadow 与 real schema 相同但数据隔离;
- 下游服务继承染色标记;
- 消息队列按染色标记分流到 shadow topic;
- 监控、告警对染色流量打标签,不触发业务告警但保留观测。
关键设计约束:
- 不写入真实资金数据:影子库账户必须隔离,金额不能流向真实清算;
- 不影响真实限流:染色流量需在限流器里单独计数,或使用独立配额;
- 可以关闭:压测结束后一键关闭染色透传,防止真实流量误进影子链路;
- 下游不识别染色的服务必须隔离:一个外部支付通道无法识别染色 → 压测流量真的发卡,这是大事故。
9.2 峰值规划
- 春晚红包:2021 年某主流 App 春晚红包互动量达 700 亿级,峰值 QPS 千万级。这类活动的压测目标通常是峰值 3 ~ 5 倍;
- 双 11 支付:蚂蚁 2020 年双 11 支付峰值 58.3 万笔/秒,压测按 150% 以上做;
- 春节红包:微信 2023 年春节 C 端红包互动量达数百亿级,峰值 QPS 数百万。
这些数字并非目标——如果你不是头部玩家,目标应该是“业务预估峰值 × 2”。
9.3 压测的观察维度
压测报告不应只回答”到底能跑多少 TPS”,还要回答:
- SLI 在压力曲线的哪个位置崩:P99 延迟在 5 万 TPS 时从 200 ms 跃到 2 s,就该把容量目标定在 4 万;
- 瓶颈定位到组件:CPU、网络、DB 锁、线程池、GC、磁盘 IOPS;
- 链路某一环变慢时,上游的重试行为是否制造雪崩;
- 熔断 / 降级 / 限流是否在预期位置生效,生效时是否”真的有用”;
- 数据层(缓存、数据库、消息队列)的水位,以及水位到达 80% 之后还能撑多久。
几个金融特有的压测覆盖项:
- 日切(Day-End):从 00:00 日切到业务恢复的时间窗口,日切脚本在高负载下的稳定性;
- 报表批处理:月末批与日终批能否在时间窗口内完成;
- 对账文件生成:海量对账数据生成与归档,是 I/O 密集型瓶颈的常发地。
十、故障处理:从一键切流到 Blameless Postmortem
10.1 P 分级
行业较常见的故障分级:
| 等级 | 影响 | 响应 SLA |
|---|---|---|
| P0 | 核心业务大面积不可用;监管 / 重大资金安全 | 15 分钟内成立战时组;CTO / 行长级上报 |
| P1 | 单个核心业务功能不可用 | 30 分钟内成立应急组 |
| P2 | 部分功能降级 / 单机房故障 | 2 小时内处理 |
| P3 | 局部非核心功能异常 | 当日处理 |
| P4 | 观察类告警、单点小故障 | 下一次迭代修复 |
P0 / P1 触发 On-call 响应。银行通常要求 P0 在 2 小时内向人行 / 金监总局上报,上报内容包括影响面、根因初判、缓解措施。
10.2 应急预案与一键切流
好的应急预案要满足三个性质:
- 可执行:不是”处理人员联系 DBA”这种话,而是”在 XX 配置中心把开关 A 从 0 切到 1”;
- 可回滚:每一步有回滚按钮,所有切换动作有”红色 STOP”按钮;
- 可演练:预案里的每一步在演练中被实际跑过。
一键切流的骨架:
[1] 操作员在应急平台选择"切单元 1 到灾备"
[2] 平台向配置中心下发新的路由规则
[3] 配置中心推送到所有网关实例
[4] 网关按新规则路由新请求
[5] 旧请求在单元 1 内优雅结束
[6] 平台在 30 秒内显示切流进度、成功率、RT
10.3 On-call 值班体系
- 双人值班:每一个时段至少两名 On-call,一主一备,防止单点;
- 轮换:一般按周轮换;连续 On-call 超过两周的团队一定会出事;
- 呼叫链:L1 业务运维 → L2 研发 → L3 架构师 / 主管。L1 15 分钟无法定位要升级;
- 薪酬补贴:国内大厂一般有”夜班费 + 出工费”双轨;
- 手册化:每个告警有 runbook 对应,runbook 是一条可执行命令链,不是”请检查数据库”这种废话。
10.4 Blameless Postmortem(无指责复盘)
Google SRE 推动普及的无指责复盘文化,核心是:
- 关注系统而非个人:不是”张三推错了代码”,而是”代码推送流程缺少自动灰度”;
- 事实时间线:按分钟级还原全过程;
- 因果分析:用 5 Whys 或 Fishbone;
- Action Item 有 Owner、Deadline、状态:不落地的复盘等于没复盘。
金融行业这点做得比互联网难——复盘报告常会被人事、合规、监管调取,自然产生”避责倾向”。对策是分级处理:技术复盘对内 Blameless,合规报告走单独流程。这样既保留真相,又满足合规。
10.5 监控、告警、可观测性的金融版
可观测性三件套(Metrics、Logs、Traces)在金融场景里有一些特定要求:
- 业务指标与技术指标并列:仅有 CPU / RT 不够,必须有”支付成功率”“核心账务 TPS”“清算文件处理进度”等业务维度,用 Prometheus + 业务打点;
- 跨数据中心统一:多活架构下的监控必须有全局视图,任一机房看到的都是一致的;
- 告警不泛滥:P0 告警直达手机 + 电话;其余按等级分层,避免告警疲劳;
- 链路追踪:SkyWalking / Jaeger 覆盖关键链路,Trace 保留周期满足审计要求(常要求 6 个月);
- 日志合规:敏感字段脱敏、日志不能直接打印完整卡号/身份证/手机号;查询日志要有审计;
- 容量水位:CPU、内存、磁盘、连接数、线程池每一项都有”黄线”(告警)、“红线”(自动降级)两档。
一个容易被忽视的细节:监控系统本身必须是多活的。很多事故发生时监控先挂,运维失去观察能力。
十一、真实案例
11.1 光大 8·16 乌龙指(2013)
2013 年 8 月 16 日 11:05,光大证券策略投资部的套利系统因生成订单错误,向上交所提交约 234 亿元买入委托,其中成交 72.7 亿元,瞬间拉升沪指约 5.96%。后续监管调查披露:
- 订单生成系统未设置资金 / 持仓校验;
- 系统异常时订单未断路;
- 风控与账务层在数量级异常时没有独立刹车。
证监会以”内幕交易”对相关责任人处以行政处罚。这一案在工程层面推动了中国证券行业全面引入订单前置风控(Pre-trade Risk Check),即在订单抵达交易所之前,经过独立于交易系统的风控网关做额度 / 方向 / 数量校验。
启示:高可用不只是”不宕机”,也包括”不在异常时胡乱发请求”。熔断、限流、异常检测都是可用性的一部分。
11.2 AWS us-east-1 与 Coinbase(2021)
2021 年 12 月 7 日,AWS us-east-1 Region 发生大规模故障,持续数小时。Coinbase、Robinhood、Slack、Disney+ 等大量依赖该 Region 的服务中断。Coinbase 公开披露受影响,移动端与网页端在事件期间部分功能不可用。
启示:
- 单云单 Region 就是单点,无论该 Region 内部是不是多 AZ;
- 跨 Region / 跨云容灾 是金融机构对云供应商的合理预期,这也是 DORA 法案推动的方向;
- 交易类 App 的事件通常 24 ~ 48 小时内在用户与监管侧放大。
11.3 工行 / 建行手机银行(2020)
2020 年下半年,工商银行、建设银行手机银行曾发生多起公开报道的访问异常事件,包括登录缓慢、转账失败、查询余额卡顿。公开通报的口径一般是”系统升级”与”外部流量激增”。
工程层面这类事件的常见根因:
- 手机银行接入层限流不够分层,单一入口受压连锁影响;
- 活动(理财、跨境汇款促销)流量预估不足;
- 核心账务的同步复制链路抖动,导致联机交易 RT 抬升。
启示:手机银行是大多数人与银行核心系统的唯一接口,它的可用性等价于银行的可用性。接入层限流、多活、灰度必须到位。
11.4 蚂蚁 919 大促与春节红包
蚂蚁在双 11 和春节红包活动的公开分享中反复提到:
- 单元化是能够在 2019 年双 11 做到 54.4 万笔/秒、2020 年做到 58.3 万笔/秒的结构性基础;
- 全链路压测保证了活动前所有瓶颈被提前暴露;
- OceanBase 在 2019 年 TPC-C 测试中以 6088 万 tpmC 的结果打破世界纪录——这个能力直接支撑了蚂蚁的核心账务。
这类公开数据指向的结论是:单元化 + 金融级分布式数据库 + 全链路压测 是今天支撑高并发金融场景的三件套。
十二、代码示例:Go 实现简化的多活流量切换
下面用 Go 写一个可编译运行的骨架:配置中心 → 路由规则下发 → 网关按规则路由到不同单元。示例不依赖外部组件,用一个 in-memory “配置中心”与 HTTP 回调模拟规则推送。
// multiactive/router.go
package multiactive
import (
"hash/fnv"
"sync"
"sync/atomic"
)
// RouteRule 描述某个分片的写入归属单元
// Shard 取值 [0, ShardCount)
// Unit 为目标单元名,例如 "RZ-A1"、"RZ-B2"
type RouteRule struct {
Shard int
Unit string
}
// RouteTable 是一张分片 -> 单元的路由表,原子替换以实现秒级切流
type RouteTable struct {
shardCount int
table atomic.Pointer[[]string] // index: shard, value: unit
}
func NewRouteTable(shardCount int, defaultUnit string) *RouteTable {
rt := &RouteTable{shardCount: shardCount}
init := make([]string, shardCount)
for i := range init {
init[i] = defaultUnit
}
rt.table.Store(&init)
return rt
}
// Apply 按一批 RouteRule 原子更新路由表
func (rt *RouteTable) Apply(rules []RouteRule) {
old := *rt.table.Load()
next := make([]string, len(old))
copy(next, old)
for _, r := range rules {
if r.Shard < 0 || r.Shard >= rt.shardCount {
continue
}
next[r.Shard] = r.Unit
}
rt.table.Store(&next)
}
// Resolve 计算指定 key 的目标单元
func (rt *RouteTable) Resolve(key string) string {
t := *rt.table.Load()
h := fnv.New32a()
_, _ = h.Write([]byte(key))
return t[int(h.Sum32())%rt.shardCount]
}
// Snapshot 返回当前路由表(只读),便于审计与可视化
func (rt *RouteTable) Snapshot() []string {
t := *rt.table.Load()
out := make([]string, len(t))
copy(out, t)
return out
}
// ---- 配置中心与规则下发 ----
// ConfigCenter 模拟配置中心:持有一张全局 RouteTable,接受 Push,向订阅者广播
type ConfigCenter struct {
mu sync.Mutex
table *RouteTable
subs []chan []string
}
func NewConfigCenter(shardCount int, defaultUnit string) *ConfigCenter {
return &ConfigCenter{table: NewRouteTable(shardCount, defaultUnit)}
}
func (cc *ConfigCenter) Subscribe() <-chan []string {
cc.mu.Lock()
defer cc.mu.Unlock()
ch := make(chan []string, 4)
cc.subs = append(cc.subs, ch)
ch <- cc.table.Snapshot()
return ch
}
func (cc *ConfigCenter) Push(rules []RouteRule) {
cc.mu.Lock()
cc.table.Apply(rules)
snap := cc.table.Snapshot()
subs := cc.subs
cc.mu.Unlock()
for _, s := range subs {
select {
case s <- snap:
default: // 慢订阅者丢最老一条
<-s
s <- snap
}
}
}配套的网关路由器:
// multiactive/gateway.go
package multiactive
import (
"context"
"fmt"
"log"
"sync/atomic"
)
// Gateway 从 ConfigCenter 订阅路由表变化,按 user_id 路由请求到目标单元
type Gateway struct {
localUnit string
routes atomic.Pointer[[]string]
dispatch map[string]UnitClient // 单元名 -> 本地/远程调用客户端
}
type UnitClient interface {
Handle(ctx context.Context, userID string, payload []byte) ([]byte, error)
Name() string
}
func NewGateway(localUnit string, clients []UnitClient) *Gateway {
m := make(map[string]UnitClient, len(clients))
for _, c := range clients {
m[c.Name()] = c
}
return &Gateway{localUnit: localUnit, dispatch: m}
}
func (g *Gateway) Bind(cc *ConfigCenter) {
ch := cc.Subscribe()
go func() {
for snap := range ch {
cp := snap
g.routes.Store(&cp)
log.Printf("gateway=%s routes updated, shard_count=%d", g.localUnit, len(cp))
}
}()
}
// Route 决定这次请求应该由哪个单元处理
func (g *Gateway) Route(ctx context.Context, userID string, payload []byte) ([]byte, error) {
t := g.routes.Load()
if t == nil {
return nil, fmt.Errorf("route table not ready")
}
table := *t
shard := fnv32(userID) % uint32(len(table))
targetUnit := table[shard]
client, ok := g.dispatch[targetUnit]
if !ok {
return nil, fmt.Errorf("no client for unit %s", targetUnit)
}
return client.Handle(ctx, userID, payload)
}
func fnv32(s string) uint32 {
const (
offset32 uint32 = 2166136261
prime32 uint32 = 16777619
)
h := offset32
for i := 0; i < len(s); i++ {
h ^= uint32(s[i])
h *= prime32
}
return h
}端到端演示:
// multiactive/example_test.go
package multiactive
import (
"context"
"fmt"
"testing"
)
type localHandler struct{ name string }
func (l *localHandler) Name() string { return l.name }
func (l *localHandler) Handle(ctx context.Context, userID string, payload []byte) ([]byte, error) {
return []byte(fmt.Sprintf("processed by %s for user=%s", l.name, userID)), nil
}
func TestSwitchoverDrill(t *testing.T) {
cc := NewConfigCenter(100, "RZ-A1")
gw := NewGateway("GW-A",
[]UnitClient{&localHandler{"RZ-A1"}, &localHandler{"RZ-A2"}, &localHandler{"RZ-B1"}})
gw.Bind(cc)
// 初始:所有分片默认在 RZ-A1
_, _ = gw.Route(context.Background(), "user-123", nil)
// 紧急切流:把分片 0-49 从 RZ-A1 切到 RZ-A2;分片 50-99 切到 RZ-B1
var rules []RouteRule
for i := 0; i < 50; i++ {
rules = append(rules, RouteRule{Shard: i, Unit: "RZ-A2"})
}
for i := 50; i < 100; i++ {
rules = append(rules, RouteRule{Shard: i, Unit: "RZ-B1"})
}
cc.Push(rules)
// 等订阅协程消费
// 实际代码里用同步 channel 确认
got, err := gw.Route(context.Background(), "user-123", nil)
if err != nil {
t.Fatal(err)
}
t.Log(string(got))
}这段骨架故意做得简陋,但保留了真实场景里几个关键设计:
- 路由表用
atomic.Pointer原子替换,保证切流瞬间没有锁、没有半更新; - 配置中心 -> 网关是 push 模型,慢订阅者丢老消息不丢新消息;
- 分片为最小切流单位,比”整个单元切换”更细,对支持”局部故障转移”更友好;
- 单元客户端抽象(
UnitClient接口)屏蔽了本地调用和远程调用的差异,单元化与单体在接口层一致。
在真实系统里,这套骨架会被替换为:
- 配置中心:Nacos / Apollo / etcd / 自研 CDCR;
- 网关:Envoy + Lua / Nginx + OpenResty / Higress / 自研 AGW;
- UnitClient:gRPC + 单元感知负载均衡器;
- 规则审批:多级审批 + 灰度 + 指标观察 + 一键回滚。
十三、工程坑点
- 同步复制延迟反噬主库 RT:OceanBase 三副本中任意一个节点磁盘抖动,Leader 写入 RT 跟着抖。一定要有副本落盘延迟监控。
- 演练时不敢切真流量:只在预发环境切,生产演练被合规”降级”为桌面推演,真实切换能力退化。
- 配置漂移:生产热修改不经过配置中心,灾备机房上没有同步。纪律上必须彻底禁止直连改线上。
- 跨机房时钟漂移:同步写入依赖 TSO(Timestamp Oracle)时,不同机房的时钟服务器一旦漂移,幂等判重可能失效。建议使用 PTP + 边界校验。
- GTM/GSLB 缓存:DNS TTL 30 分钟,DNS 客户端进一步缓存更久。切流预期 30 秒到生效,实测 1 小时依旧有流量落到旧机房。对策:关键域名 TTL 设到 60 秒,并在应用层再加路由。
- 连接池的冷启动:切流后的新机房数据库连接池是空的,连发几万请求就是连接风暴。对策:预热 warm-up + 渐进放量。
- 消息重复消费:跨机房切换后,消息积压回灌,幂等性设计差的业务会重复扣款。幂等键要持久化,参考本系列 第 5 篇。
- 监管报送通道单点:核心业务多活,但报送接口写死 A 机房 IP。报送失败就是监管函。报送链路也要做多活。
- 双活变双死:同城两个机房都能写、没有仲裁,网络抖动时双方都认为自己是主。必须有独立仲裁(Zookeeper/etcd/专门仲裁节点),且仲裁放在第三机房。
- 应急预案过期:一年前写的预案,脚本命令已经失效、联系人已经离职、系统名已经改了。预案必须随代码一起进 Git,每次演练后更新。
十四、选型与落地清单
14.1 选型判断
| 你的现状 | 推荐阶段 |
|---|---|
| 单机房、主备未落地 | 先把主备跑稳、演练过三次再谈双活 |
| 同城双活已稳定、异地冷备 | 异地灾备激活(至少每季度切一次) |
| 两地三中心稳定 | 评估单元化 ROI(用户过亿、DB 容量/爆炸半径有压力再做) |
| 单元化已上线 | 关注跨单元事务治理、演练平台自动化、全链路压测闭环 |
14.2 落地清单(对着这个 checklist 走)
架构:
部署:
运维:
复盘:
十五、与本系列其他章节的交叉引用
- 金融级数据库分片与热点账户:《账务数据库设计》
- 异地多活下的幂等与 SAGA:《幂等、事务与一致性》
- 多活对对账的放大效应:《对账系统工程》
- 清算 / 结算时间窗与灾备窗口的耦合:《清算 vs 结算 vs 资金归集》
- 支付通道熔断与路由:《支付网关设计》
- 实时风控的高可用部署:《实时风控引擎》
十六、参考资料
- 中国人民银行官网:https://www.pbc.gov.cn/
- 国家金融监督管理总局:https://www.nfra.gov.cn/
- GB/T 20988-2007 《信息系统灾难恢复规范》:https://openstd.samr.gov.cn/
- 《银行业金融机构信息科技外包风险管理指引》(原银监会)
- FFIEC Business Continuity Management Handbook:https://ithandbook.ffiec.gov/
- EU DORA Regulation (EU) 2022/2554:https://eur-lex.europa.eu/eli/reg/2022/2554/oj
- Google SRE Book(Blameless Postmortem 章节):https://sre.google/sre-book/postmortem-culture/
- 蚂蚁集团 OceanBase 技术白皮书:https://www.oceanbase.com/
- Chaos Mesh 文档:https://chaos-mesh.org/
- ChaosBlade 项目:https://chaosblade.io/
- AWS us-east-1 2021-12-07 事件 Post-Event Summary:https://aws.amazon.com/message/12721/
- 中国证监会关于光大证券异常交易事件的处理决定(2013):公开行政处罚决定书
下一篇:《金融科技工程展望:AI 风控、稳定币、开放银行、Web3 合规》
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【金融科技工程】账务数据库设计:TiDB/OceanBase/Postgres 下的分片、索引、热点账户
账务(Ledger)数据库是金融系统最硬的那块骨头。本文从 RPO/RTO 目标出发,对比 PostgreSQL、MySQL、OceanBase、TiDB、CockroachDB、Oracle、TigerBeetle 等主流选型,讲分片维度、热点账户拆解、索引设计、冷热归档、MVCC 并发控制与审计合规,辅以蚂蚁、Stripe、PayPal、Square 的真实演进路径。
金融科技工程
面向中国工程团队的金融科技系列。从账务底盘、支付、清结算、交易所、风控合规到可靠性与灾备,中国与全球视角并举,讲清楚金融系统在工程落地中的真实挑战。
【金融科技工程】金融科技工程全景:从支付到交易所的系统分类与读图
金融科技(FinTech)不是普通后端加一张账户表。钱的原子性、监管的硬边界、一个小数点的代价,把这个领域推进到工程强度最高的那一档。本文是【金融科技工程】25 篇的总目录与阅读地图:先交代为什么它比一般业务系统更难,再给出对账体、支付体、交易体、风控合规体四维分类,把后续 24 篇挂到骨架上,最后给出一份绿地项目的落地顺序建议。
【金融科技工程】钱的建模:金额精度、币种、会计单位、多语言金额
在代码里正确地表示"一笔钱"远比看起来难。本文系统梳理金额的数值建模(浮点、定点、Decimal、最小单位)、币种标准(ISO 4217)、本地化显示、汇率换算与数据库存储,并给出 Go、Python、Java、Rust 的工程化示例。