1 数据架构要回答什么
零售订单 API 接收下单请求,保存订单与明细,再向顾客返回订单编号。客服随后查询订单,运营查看每小时成交额,财务在次日核对退款。它们都在使用“订单数据”,但对速度、准确性、保留时间和查询方式的要求不同。数据架构的任务,就是把这些要求变成可解释、可运行、有人负责的数据流,而不是先画几个数据库图标。
本课沿用零售订单 API 场景,并给出用于练习的明确假设:日订单量为 100 万,促销峰值为每秒 300 次下单,在线下单的服务端响应时间目标为第 95 百分位不超过 300 毫秒。这个百分位表示约 95% 的请求在目标时间内完成。运营接受成交看板最多延迟 60 秒;财务要求每日 09:00 前提供前日对账结果,金额差异必须可以追溯。真实项目应重新测量这些数值。
先区分业务事实与观察结果。订单是否创建成功,应由订单服务提交的交易记录回答;“今天成交多少”则是按某种口径计算的结果。创建时间、支付时间、退款时间可能跨日,用不同时间统计会得到不同数字。数据架构必须说明每个数字来自什么事实、经过什么加工、何时有效,不能把“报表有数”当成口径已经正确。
接着回答数据在哪里产生、由谁修改、向谁提供。订单服务拥有订单状态及其变化规则,支付服务提供支付事实,报表使用这些事实计算指标。即使练习中把数据放在同一套基础设施里,业务边界也要清楚。否则,运营为调整报表直接修改订单状态,可能让客服、退款流程和财务同时失去可信依据。
数据架构还要回答失败时会发生什么。交易已经成功而报表尚未更新,是可以解释的延迟;交易没有成功而报表已计入收入,则可能是错误事实。需要分别描述在线请求的成功条件、数据传递的恢复方式和报表的可用条件。把这些条件写清楚,才能决定哪些环节必须同步完成,哪些环节可以排队处理。

最后才讨论技术选项与成本。可以从操作库定时导出,也可以捕获已提交的变化;可以建设独立分析库,也可以先提供少量固定汇总。选择取决于延迟目标、查询规模、团队维护能力和失败影响。数据库产品名称本身不能证明选择合理,某种存储支持的功能也不等于团队已经具备运行它的能力。
本课的方案路径是:先明确订单事实和消费需求,再划分存储职责,建立数据契约,画出正常与失败的数据流,最后用架构决策记录说明取舍。这里的 ADR,即架构决策记录,是保留背景、备选项、结论和重评条件的短文档。它让下一位维护者知道当时为何这样做,而不只看到已经落地的组件。
2 操作库、分析库与湖仓边界
操作库面向正在发生的业务操作。在本例中,创建订单需要保存订单头、订单明细及初始状态;客服通常按订单编号查询,订单服务按业务规则更新状态。它追求的是明确且短小的操作、可靠提交和稳定响应。如果相关记录处于同一事务边界,可以让它们共同成功或共同失败,避免出现只有订单头却没有明细的半成品。
分析库面向跨越大量记录的统计和比较,例如按门店、渠道及日期汇总净支付额。它经常需要读取大量历史数据,并连接多个主题。查询可以比在线请求更慢,却应避免干扰下单。在分析库保留订单明细、再生成面向看板的汇总表,是为不同访问方式分工;它不应反过来成为修改订单业务状态的入口。
湖通常指以文件为重要载体、容纳较多原始或加工数据的存储组织方式,仓强调经过治理、便于分析的数据集合,湖仓方案尝试在文件基础上提供更多管理与分析能力。入门阶段应关注共同问题:数据是否有目录、结构和责任人,读取方是否知道版本与质量。把文件放进对象存储,并不会自动得到可信的数据平台。
这些边界主要由用途与责任决定,不是把某种技术永远归入某一类。规模较小时,独立关系型数据库也能承接固定分析任务;规模扩大后,才可能需要更适合大量扫描的布局。反过来,即使某套系统能同时处理交易与分析,也仍需验证资源隔离和故障影响。功能清单不能替代负载证据。
本例先选择操作库处理订单交易,独立分析库提供运营明细与汇总,对象存储保存经批准的历史归档和重放输入。暂不建设通用湖仓平台,因为当前只有明确的订单分析需求。归档范围也要有边界:只保存恢复和审计确实需要的数据,注明保留期限,不把所有含个人信息的原始记录无限复制到每个环境。

同一事实在不同位置出现,需要解释这些副本之间的关系。操作库里的订单状态是业务判断依据,分析库里的订单状态是某个处理水位以前的副本,归档是指定范围的历史材料。报表应展示“数据更新至什么时间”,避免使用者把副本误当成当前真相。归档能否恢复,还取决于是否保留结构说明以及能否完成恢复演练。
成本比较也要遵守边界。操作库成本包含交易容量、备份和高可用;分析侧还包含扫描、转换、保存副本以及值班维护。新增对象存储可能降低部分历史保存成本,却会引入目录、权限、清理和回放管理。先画清每份数据的用途与生命周期,再比较总成本,才不会把便宜的存储单价误当成便宜的整套架构。
3 所有权、契约与演进
数据所有权是对业务含义与变更负责,不只是拥有建表权限。订单团队应解释“已取消”是否允许支付、何时生成订单编号以及订单金额如何计算;分析团队负责把这些定义转成正确的汇总与展示。平台团队可以维护传输和存储设施,但不能自行决定取消订单是否计入成交。职责不清时,最容易出现每个系统都正常、数字却相互矛盾的情况。
数据契约是生产方与消费方共同遵守的约定。它至少描述标识、字段含义、允许值、单位、时间语义、版本和质量要求。例如订单编号用字符串保存以保留前导零,金额使用整数分并带币种,业务发生时间与数据采集时间分开记录。约定时间采用 UTC,报表再按指定营业时区划分日期,可以减少跨地区统计中的歧义。
状态变化记录可包含 event_id、order_id、order_version、occurred_at、schema_version 和本次状态。event_id 标识这条变化,order_version 表示同一订单的业务先后,schema_version 表示记录结构的版本;它们解决不同问题,不能互相替代。涉及退款时还应有独立退款标识,因为同一订单可能发生多次部分退款,不能只靠订单编号去重。
契约还需要明确内容是否完整。如果传递的是变更字段,消费方必须结合之前状态还原;如果传递的是约定字段的完整订单快照,消费方可以按版本替换,但体积可能更大。本例为入门练习选择完整的分析所需字段快照,并省略与分析无关的敏感字段。消费方不会据此更新交易,只维护自己的分析副本。
演进时先判断语义是否兼容。新增可选字段通常比删除字段容易,但也要考虑旧消费方能否忽略未知字段。把金额从“分”改成“元”,即使字段名和类型不变,也属于含义破坏。应发布明确的新字段或版本,提供过渡期,并在切换前比较新旧结果。数据量越大,错误单位被复制得越广,修复成本就越高。

以增加优惠分摊字段为例,订单团队先定义分摊规则与舍入方式,分析团队再验证明细合计能否回到订单金额。新旧字段并存期间,选取正常支付、取消、部分退款和跨日退款样本进行比较。消费方确认支持后再安排切换,旧字段达到约定停用日期后才清理。不能只看到接口部署成功,就认定所有历史报表已经正确。
所有权最终要落实到可联系的人和可执行的流程。契约应注明维护团队、变更通知渠道、故障响应职责和受影响的消费方清单。发现未知状态值时,分析侧应隔离异常并告警,不应悄悄映射为“已支付”。同时保留失败记录以便修复后重放,让发现问题、解释业务和恢复数据能够形成闭环。
4 动手:画一条从交易到报表的数据流
先画最小范围:顾客提交订单,订单服务提交交易,已提交变化进入传输通道,转换任务维护分析明细,再刷新运营汇总,最后由看板查询。图上的每条箭头都要写清数据内容和触发条件。“同步数据”过于含糊,应改成“捕获已提交订单变化”或“每隔 30 秒刷新汇总”。箭头越具体,越容易发现缺失的责任与恢复路径。
本例选择变化数据捕获,简称 CDC,即从操作库已提交的变化中获取后续处理的输入。先理解它解决的问题:让业务提交与分析传递之间有可追踪的衔接。不要在请求处理中分别写操作库与分析库,再假设它们总会同时成功。至于具体日志格式、连接器实现和复杂事务边界,留到实现选型时深入。

现在用订单 O1042 走图。订单头和明细提交后,API 才返回成功;CDC 随后看到该次提交。分析任务检查记录结构和必填字段,用订单编号定位副本,再按版本更新,最后由汇总任务计算指标。API 的成功不等待汇总完成,因此报表暂时没有这笔订单不意味着下单失败,前提是延迟仍在约定范围内。
接着在图上增加重复与先后关系。传输恢复时,同一事件可能再次到达;某些路径还可能让同一订单的旧版本晚到。分析处理需要识别事件标识,并避免旧版本覆盖新版本。本例使用完整快照,允许按订单版本维护最新副本;若改成增量扣减,跳过中间版本可能丢失金额变化,处理规则就必须重新设计。
画完增量路径还不够,已有历史数据也要进入分析侧。首次装载需要划定快照范围,并与增量起点衔接,避免重复或遗漏。课堂上可用包含截止位置的历史快照表达这个交接,不必展开具体数据库的快照机制。方案中仍要写清是谁验证交接范围、用什么订单样本及金额总额确认没有空洞。
在每段箭头旁增加恢复信息:源变化保留多久,传输从哪个已确认位置继续,异常记录放在哪里,重放由谁发起。只在目标写入成功后推进对应处理位置;如果无法同时记录处理结果和去重状态,就要说明故障后如何识别并修正重复影响。不要把“有队列”当成“不会丢数据”的充分理由。
最后给这张图标注验收证据。选取下单、取消、支付及部分退款样本,记录源订单版本、分析侧版本、汇总水位和金额结果;模拟分析任务暂停后恢复,检查追赶及重复处理。还应保留按营业日核对的总额和异常清单。流程图因此从组件摆放图变成可以追踪正常、延迟、重复与恢复的交付说明。
5 一致性与查询灵活取舍
一致性首先要落到用户动作上。顾客刚创建订单就打开详情页,通常希望看到创建结果,因此详情查询应访问能满足该读写要求的操作路径。运营看趋势则可以接受短暂延迟,使用分析副本。不能用“系统采用最终一致性”概括所有接口,因为同一系统里的下单确认、订单详情和经营看板,可能需要不同承诺。
最终一致性的入门含义是:当更新停止、传输和处理恢复正常后,副本能够按规则追上源事实。它没有自动承诺延迟上限,也没有自动解决错误口径。要实现运营看板的 60 秒目标,还需要容量、监控和恢复流程。若积压持续增长,即使每条记录最终都能送达,也可能长期无法满足业务的可用要求。
查询灵活性同样有代价。保留细粒度明细,能回答新出现的渠道或商品问题,但会增加存储、扫描和治理成本;提前生成汇总,能让常见看板更快,却难以回答汇总维度之外的问题。本例保留有限期限的订单分析明细,并为固定看板生成汇总。新增报表先评估现有数据能否支持,再决定是否扩展契约。
看板新鲜度可拆成变化传递耗时与汇总等待时间。为了直观比较,下面的交互假设变化在 5 秒内进入分析明细,汇总按固定间隔刷新,且转换与查询容量足够。拖动刷新间隔,会看到延迟与扫描量一起变化。这个教学模型没有包含故障和排队,不能替代压测,也不能直接当作实际服务保证。
例如每隔 30 秒刷新,在上述假设下,典型等待约为 20 秒,最坏等待约为 35 秒;每隔 300 秒刷新,最坏等待约为 305 秒,便不满足 60 秒目标。如果每次扫描相同的 200 MiB 分析数据,缩短间隔会增加扫描总量。这说明新鲜度需要支付资源成本,也提示团队可以改进汇总方式,而不是无限加快全量扫描。
金额统计还需要区分更新与更正。今天收到昨天发生的退款,应按财务约定更新对应账期或生成调整记录,不能为了让当前看板好看而丢弃迟到数据。报表可以同时呈现业务发生日期与处理日期,并标明结果是否已关账。快速看到近似趋势与获得可审计的最终金额,是不同使用场景,应分别定义验收方式。
方案中的 ADR 可比较 3 个选项:报表直连操作库、独立分析库定时装载、CDC 加独立分析库。对本例而言,前者难以控制交易影响,定时装载若要满足 60 秒目标需要验证扫描成本,CDC 则增加运行复杂度。选择 CDC 的理由应是经过验证的延迟和隔离需求,而不是它听起来更实时;若需求放宽到次日报表,决策就可能改变。
还应列出重评条件。比如分析数据量增长后扫描费用超出预算,新增消费者提出不同的时间口径,或团队无法维持连接器值班,都可能触发调整。取舍不是在快、准、便宜之间随意选 2 个,而是把每项要求的范围、代价和证据说清楚,再确认业务愿意承担哪些限制。
6 常见坑:报表直连生产库
报表直连生产库常从合理的小需求开始:运营只想多看几个字段,现成查询跑几秒就能出结果,于是给报表工具创建只读账号。只读限制了修改数据的能力,却没有限制读取时消耗的处理器、内存、连接及磁盘吞吐。随着历史数据增长,原本轻量的查询可能变成大量扫描,并与下单事务争夺资源。
促销期间,报表为了计算各门店成交额,把订单、明细和退款记录连接起来,再按日期聚合。单次查询可能同时读取大量行,多个用户重复刷新还会放大负载。交易接口开始变慢时,团队容易先增加 API 实例,结果更多请求继续进入同一操作库。应用层扩容没有消除数据库瓶颈,甚至可能让排队更严重。

排查要关联时间线,而不是看到数据库忙就猜测原因。把订单 API 的第 95 百分位延迟、数据库活跃查询和等待、报表任务开始时间放在同一时间轴上。检查是否有长时间扫描、连接池占满、存储读取上升,必要时再查看查询计划。某个指标同时上升只能提供线索,还要用受控停止或限流验证因果关系。
恢复时先保护已经承诺的交易目标。可以暂停高成本报表任务、限制报表并发,并让看板展示最近可用结果及更新时间。接着检查交易是否恢复、连接积压是否消退。不能为了让报表看起来最新而关闭延迟提示,也不能未经评估就终止所有数据库会话,因为其中可能有正常交易,造成更多重试与业务不确定性。
增加只读副本是常见缓解措施,但要知道隔离范围。它可以转移部分查询执行压力,仍可能存在复制延迟、共享存储或网络成本;具体影响取决于部署方式。副本也未必适合无限增长的历史连接分析。应通过负载测试证明隔离效果,并在报表中说明水位,不能把“读副本”直接写成“交易绝不受影响”。
长期治理包括独立分析访问入口、查询配额、超时限制和明确的数据产品。给固定报表提供经过验证的汇总,比允许任意工具扫描生产表更容易控制;临时分析可以走申请范围明确的分析明细。限制也应有业务解释,例如高峰期降低刷新频率,并显示数据时间,而不是静默返回看似实时的旧值。
验收隔离效果时,要让报表高负载与订单峰值同时出现,观察交易目标能否持续满足;还要在分析服务不可用时确认下单仍可进行。这种证据比只测单条报表快多少更有价值。它证明故障边界确实成立,也为后续高可用设计提供依据:分析侧出故障应造成报表变旧,而不是把订单入口一起拖垮。
7 案例:宽表变更拖垮上游事务
宽表把分析经常需要的多个字段放在同一张较宽的表中,以减少查询时的连接。在本例中,运营希望同时查看订单、门店、优惠和退款标签,分析团队于是维护订单宽表。宽表本身不是错误;问题出现在建设过程为了方便,把宽表更新同步放进下单事务,让报表结构开始影响交易提交。
最初,宽表只有少量字段,同步写入看起来很快。后来新增优惠标签,转换逻辑需要查询额外规则;上线时又补算历史订单。新逻辑使下单事务持续更久,历史补算与在线写入竞争资源,订单接口超时增加。客户端重试又推高请求量。如果没有清楚的事务边界,这条链路很容易被误判为 API 实例数量不足。
定位时先比较变更前后的提交耗时与事务持续时间,再确认宽表写入是否位于请求成功之前。检查慢查询、等待和历史补算的时间范围,核对同一时段是否发布转换规则。随后在受控环境关闭新增加工,观察交易耗时是否恢复。不要仅凭“刚发布过”就下结论,也不要直接把所有异常归因于表的字段数量。

止损可以先停历史补算,并按预先约定的开关撤回同步加工,使交易回到最小提交边界。执行前需确认业务订单记录仍完整,停用的是分析派生结果;如果新增字段已经参与业务判断,就不能简单跳过。回滚后保留受影响订单范围、已发布版本与处理位置,避免恢复报表时再次遗漏或重复计算。
结构修复把宽表加工移到交易成功之后,通过可靠捕获的变化维护独立分析副本。新版宽表先在独立输出位置构建,核对行数、关键金额和典型订单,再切换报表读取入口。旧版保留约定的回退窗口。这样,报表字段与转换规则可以演进,而不要求订单事务同步执行每次新增的分析逻辑。
历史补算同样需要控制资源。按明确日期或订单范围分批处理,设置并发上限,并优先保证实时路径的容量;遇到同一订单的新变化时,按版本和既定规则合并,避免历史快照覆盖更新结果。记录批次边界、成功范围与异常范围,才能在中断后继续。全量重新跑并不天然比局部修复更安全。
修复验收包括交易性能、数据完整性和恢复能力。促销负载下重新发布宽表字段,检查订单响应是否稳定;故意暂停分析任务,确认下单成功且看板清楚显示延迟;恢复后核对支付与退款总额。案例应留下的 ADR 结论是“分析派生不进入订单成功的必要路径”,并说明为此接受的副本延迟与运行成本。
8 把数据所有权写进架构方案
架构方案中的所有权表应从业务对象出发。订单团队负责订单编号、状态及订单版本,支付团队负责支付与退款事实,分析团队负责指标口径实现、汇总水位和报表质量。平台团队负责约定范围内的传输与存储运行。不能把“数据库由平台维护”写成“数据问题都由平台处理”,因为平台无法替业务团队裁定金额含义。
每份数据产品要说明输入、输出和承诺。例如运营订单汇总接收已提交的订单及支付变化,输出按门店和营业日计算的净支付额,目标新鲜度为 60 秒。退款口径、迟到数据处理、版本与更新时间都属于契约。报表异常时,使用者据此判断是缺少输入、加工错误还是等待尚未结束,而不是在多个团队之间转发截图。
质量责任需要配套证据。生产方检查必填字段、合法状态和金额单位;分析方检查重复记录、版本倒退、关联缺失与汇总差异。双方共同维护少量具有业务代表性的样本,特别是取消、部分退款和跨日变化。行数相等不足以证明金额正确,金额总和一致也可能掩盖分组错误,因此应结合总体核对与抽样追踪。
成本章节应列出可计算的组成项:操作与分析数据规模、每日变化量、复制网络、汇总扫描、归档保留、备份以及运行维护。用平均记录大小乘订单量只能得到起点,还要考虑订单明细、退款、索引和副本。把假设与测量值分开,给增长区间,并注明达到预算阈值后优先缩短明细保留、调整汇总还是重新选型。
高可用也应按责任分开承诺。订单链路可用性决定顾客能否下单,分析链路可用性决定看板能否保持新鲜。前者故障时按交易恢复目标处理,后者故障时允许暂用明确标时的旧结果,并依靠保留输入追赶。隔离执行资源、设置容量上限和准备恢复步骤,比只给数据库添加副本更接近完整方案。
恢复目标要写到数据层面。恢复点目标 RPO 表示可接受丢失多长时间范围的数据,恢复时间目标 RTO 表示希望多久恢复服务。本例假设交易目标为已确认订单不因单个故障域失效而丢失、30 分钟内恢复;这需要相应的复制、故障切换及演练支持,不能仅靠备份宣称达到。分析侧则假设 2 小时内恢复到 60 秒新鲜度以内。
为了支持上述分析恢复目标,可先约定源变化保留 72 小时,再通过实测确认故障发现、修复与追赶总时间不超出保留窗口。追赶能力必须高于同时到来的新变化,否则恢复任务只能维持积压。超窗后应走历史装载和增量衔接流程。方案应记录演练结果与责任人,让所有权同时覆盖平时变更、成本控制和故障恢复。
9 从数据架构走向安全架构(P19)
数据流画清楚以后,安全问题就有了具体落点。订单中可能包含姓名、手机号和收货地址;运营统计成交趋势通常不需要这些原始信息。应在契约阶段列出每个用途需要的最少字段,把个人信息与分析指标区分管理。复制到分析库、归档或测试环境的每份数据,都增加了需要解释访问理由和保留期限的位置。
沿着本课的数据流逐段提问:谁能读取操作库的已提交变化,传输身份能访问哪些表,分析任务是否需要完整地址,报表用户能否导出明细,重放输入是否包含已经到期的数据。答案应关联具体团队、身份与用途。只在图外写“统一鉴权、全程加密”,无法说明授权范围,也无法防止拥有过大权限的合法账号误用数据。
所有权与安全责任需要衔接。订单团队确认字段敏感程度与允许用途,分析团队控制派生数据的展示和导出,平台团队落实约定的身份、权限和审计能力。删除或更正请求也要考虑副本、缓存和归档的处理规则,不能只改操作库就结束。具体实施应结合适用要求与业务保留义务,在后续安全方案中明确。
数据可追溯性为安全设计提供基础。能从报表指标追到分析记录、源事件和订单版本,既有助于解释金额,也有助于调查异常访问及错误更正。但可追溯不代表把完整敏感内容复制进每条日志;日志应尽量记录标识、动作、时间和结果,并控制可见范围。调试便利不能成为扩大数据暴露面的默认理由。
进入 P19 前,交接材料应包含数据流图、对象与字段清单、所有权、消费方、保留规则、恢复入口和需要审计的关键操作。安全架构将在这些已明确的边界上补充身份认证、授权、保护和审计设计。若某条数据流连用途和负责人都不清楚,应先补齐数据架构,再讨论给它配置什么安全措施。
放进方案里
零售订单 API 的订单事实由订单团队维护,支付及退款事实由支付团队维护。下单成功以操作库事务提交为准,在线详情走满足读写要求的操作路径。练习容量为每日 100 万笔订单、峰值每秒 300 次下单,第 95 百分位响应时间目标为 300 毫秒;上线前以实测校准容量与余量。
采用已提交变化捕获,将分析所需字段送入独立分析库,运营汇总每隔 30 秒刷新,目标新鲜度为 60 秒。报表显示实际数据水位,次日 09:00 前完成前日对账。订单编号、事件标识、订单版本、金额单位、币种及时间语义纳入契约,由生产方与消费方共同评审。分析团队负责去重、版本处理、异常隔离和金额核对。
ADR 比较生产库直查、定时装载及变化捕获方案,基于交易隔离与延迟需求选择后者,并记录增加的维护成本。预算覆盖分析存储、传输、扫描、归档、备份及运行投入,依据实际订单明细量和增长区间测算。若报表只需次日更新,或维护投入超过预算,应重新评估定时装载。
分析加工不进入订单提交的必要路径。分析故障时保留交易服务,看板标明延迟;源变化暂定保留 72 小时,分析恢复目标为 2 小时内追到约定水位,并以演练验证追赶容量。交易按已确认订单在单个故障域失效时不丢失、30 分钟内恢复的目标建设与演练。保留窗口不足时走历史装载恢复。
验收同时覆盖订单峰值、报表高负载、重复投递、任务中断和宽表变更。证据包含接口延迟、处理水位、版本与金额核对、恢复耗时及异常清单。进入安全设计前,补齐字段敏感程度、访问主体、最少字段与保留规则;跨团队变更必须更新契约、负责人和受影响消费方记录。
10 小结:下一步安全架构(P19)
数据架构把业务事实、存储用途、所有权、契约与恢复连接起来。零售订单案例的关键选择,是让交易提交保持清楚的边界,让分析通过可追踪的数据流获得副本,并用水位、核对和演练证明承诺。
自测可以围绕 3 个问题展开:报表少了订单时,如何判断是交易失败还是分析延迟?金额字段更换单位时,谁负责评审与迁移?分析停机超过保留窗口后,如何恢复并证明没有遗漏?若能沿着图给出责任、证据与步骤,就可以进入 P19,把身份、权限、保护与审计落实到同一条数据流上。