Hacker News 中文摘要

RSS订阅

金融科技工程手册 -- Fintech Engineering Handbook

文章摘要

该手册介绍了金融科技软件工程的核心模式,强调“不创造数据”和“不丢失数据”两大原则,通过幂等性、去重、对账、事件溯源等技术保障资金系统的可靠性,适合金融科技从业者及外部人员参考。

文章总结

好的,这是对《金融科技工程手册》主要内容的精炼中文重述,保留了核心细节,并删减了与主题无关的冗余内容。


金融科技工程手册:核心内容精要

本手册旨在阐述以“金钱”为核心系统的软件工程关键模式,帮助金融科技从业者构建可信赖的金钱系统。其核心遵循三大原则:

  1. 不凭空创造数据:金钱不能无中生有,必须通过幂等性、去重和对账来杜绝重复或任意余额更新。
  2. 不丢失数据:所有金钱变动必须被追踪和持久化,通过全精度计算、至少一次投递、事件溯源、审计追踪和不可变性来保障。
  3. 不信任:不信任外部供应商、内部组件乃至整个世界。通过验证Webhook、跨源交叉核对数据,并在假设被打破时果断报错来维护系统安全。

一、 金钱的表示

正确表示金钱是基础,错误会向上传导。

  • 精度处理:有四种主要方式,绝不应使用浮点数

    1. 浮点数:有不可预测的精度损失,几乎总是坏主意。
    2. 任意精度(如Java的BigDecimal):可精确控制计算精度,适合汇率计算等中间运算。
    3. 最小单位精度:将金额以最小单位整数存储(如€12.34存为1234),适用于大多数法币。加密货币也类似,但精度由代币自身定义(如18位),可能超出64位整数范围。
    4. 有理数:当不允许任何精度损失时使用,但速度慢且难以转换。
    • 序列化:传输金额时,应使用字符串(如"12.34")或最小单位整数,避免使用JSON数字(其本质是双精度浮点数)。
  • 舍入策略

    1. 舍入不可避免,应显式执行
    2. 舍入是业务决策,有法律/税务影响。
    3. 尽可能晚地舍入,通常在持久化或展示给用户前进行。
    4. 舍入会破坏总和,可能需要设置专门的“舍入账户”来处理残差。
  • 货币处理

    1. 将金额和货币打包在一起(如Money类型)。
    2. 禁止跨币种算术,转换必须使用严格控制的汇率。
    3. 使用受控的货币集合,在系统边界验证。
    4. 货币代码仅对法币唯一,加密货币需更复杂的标识。
    5. 注意,挂钩、桥接或包装的加密货币与底层资产并不等价。
  • 汇率

    1. 汇率是有方向性的(买入/卖出价不同)。
    2. 汇率的时间点至关重要(当前时间 vs. 价值日期)。
    3. 区分交易汇率(实际转换的汇率)和参考汇率(用于估值)。
    4. 没有权威汇率,来源应作为数据的一部分。

二、 记录金钱:账本

  • 复式记账:以(贷方账户, 借方账户, 金额)形式记录交易,确保资金守恒。余额从不存储,而是从交易中推导得出。账户有类型(资产、负债、权益等),已过账条目不可变。

  • 时间戳:交易通常有三个时间:价值时间(发生时间)、记账时间(记录时间)和结算时间(资金实际转移时间)。它们通常不一致,需分别记录。

  • 审计与审计追踪:系统需记录完整历史,以回答审计问题。审计追踪应捕获每次变更的内容、时间、触发者(谁/什么)和原因。事件溯源是实现审计追踪最系统化的方法,但会增加系统复杂性。记录必须不可变,修正通过发布新的补偿条目实现。

  • 冲销与更正:错误通过“向前修正”处理,即发布新的补偿条目并链接到原始记录。注意,更正可能落在不同的报告期。

三、 执行资金流

  • 不变量:系统必须始终满足的属性(如会计等式)。通过构造方式(使无效状态不可表示)、运行时检查事后分析(如对账)来共同保障。

  • 资金预留:在与外部交互前,先预留资金,避免竞态条件。这引入了总余额可用余额的区分。预留必须最终被结算或释放,且需要强一致性。

  • 处理透支:透支分有意(信贷产品)和无意。即使系统正确,外部世界也可能导致无意透支。不应在类型或存储层面强制“余额非负”,而应通过运行时检查和事后监控来处理,并明确记账和追回。

  • 幂等性:在分布式系统中,通过重试保证投递,但处理必须幂等。优先使用显式的幂等键,并确保其原子性。注意处理错误重放、并发访问和超时窗口等问题。

  • 完全可恢复性:资金流可能在任何步骤失败。应将流程建模为持久化的状态机,每个步骤完成后提交进度。需要一个独立的驱动来恢复停滞的流程。每个步骤必须可安全重跑(幂等),失败时要么向前重试,要么通过补偿动作回滚(Saga模式)。

四、 与外部世界交互

  • 消费API:不信任外部API的架构、质量和可用性。在边界验证重要数据,预期所有调用都会失败,并做好重试和超时。存储每一次请求和响应作为审计证据。考虑关键环节的供应商冗余。

  • 处理Webhook不信任Webhook。不假设其顺序、有效性、投递或单次投递。将其视为“某事发生了”的提示,而非事实。快速确认并异步处理,持久化原始载荷,并验证调用者身份。

  • 可靠通知:为确保状态变更后可靠地通知外部,可使用发件箱模式(将发布意图与状态变更一起事务性地写入数据库)或变更数据捕获(CDC,从数据库日志中捕获变更)。投递是“至少一次”,消费者必须幂等。

  • 对账:用于发现和修复系统间的数据偏差。需确定对账节奏、偏差性质、匹配算法,并处理一对多匹配。发现差异后,应通过一等支持(如更正记录)来理解和修复,而非简单覆盖。

五、 控制与访问

  • 职责分离与四眼原则:敏感操作(如大额提现、账本更正)需要第二人批准。这同样适用于工程操作(如合并代码、部署)。审批记录是审计追踪的一部分。需提供紧急情况下的“破窗”路径。

  • 访问控制:遵循最小权限原则,使用基于角色的访问控制(RBAC)。授权变更本身也需要审计追踪。定期审查访问权限。

  • 变更追踪:代码如何进入生产环境也需可审计。版本控制和CI/CD系统是记录,应通过强制审查、状态检查和禁止直接推送来保障。

六、 测试

金融系统测试的难点在于无法穷举所有场景。推荐以下方法:

  • 基于属性的测试:断言不变量对任何生成的输入都成立。
  • 步骤间不变量检查:在操作序列的每一步后都检查不变量。
  • 生成式幂等性测试:自动重复所有操作,断言第二次调用无影响。
  • 崩溃与恢复注入:在流程的任意两步之间注入故障,测试可恢复性。
  • 往返测试:编码/解码、序列化/反序列化后,断言回到起点。
  • 黄金测试:将计算结果与存储的预期结果对比,发现意外变更。
  • 向后兼容性测试:确保新代码能正确读取旧格式的数据。
  • 生产环境测试:通过金丝雀发布或合成交易,在真实环境中验证集成。注意,这些测试会移动真实资金,必须走完整的账本、对账和审计流程。

附录A 提供了金融科技领域的关键术语表,涵盖会计、支付、交易、托管、合规等方面。

附录B 通过三个端到端示例(加密货币提现、银行卡充值、应用内兑换返现),展示了上述模式如何在实际流程中协同工作,强调了“不信任”和“不凭空创造数据”等原则的具体应用。

评论总结

根据评论内容,总结如下:

主要观点与论据:

  1. 内容价值与真实性:多数评论认可该手册的实用价值,认为其基于真实行业经验。评论6(评分None)指出:“I have just left a fintech company after 5 years... it looks legit to me... These are the same sort of lessons I learned during my time in the industry.”(“我离开金融科技公司5年后...看起来是真实的...这些是我在行业中学到的同样教训。”)评论1(评分None)强调:“The idempotency keys section alone is worth the read most devs learn that lesson the hard way.”(“仅幂等键部分就值得一读,大多数开发者都是通过艰难方式学到这一课。”)

  2. 内容深度与争议:部分评论认为手册浅显或存在错误建议。评论9(评分None)批评:“I found this handbook shallow and - in some areas - even bad advice... monetary value stored in something else than integers... It's always integers unless you have a VERY good reason to do otherwise.”(“我发现这本手册浅显,在某些领域甚至是糟糕的建议...货币值应始终用整数存储,除非有非常好的理由。”)评论3(评分None)则反对“minor-units precision”策略,建议在JSON API中使用字符串表示金额:“consider representing amounts as a string type in JSON-based APIs... JSON does not specify decimal precision.”(“考虑在基于JSON的API中用字符串表示金额...JSON未指定小数精度。”)

  3. 适用性讨论:评论7(评分None)认为手册内容适用于通用软件工程:“I think most of this applies to software engineering generally, not just fintech... retries, idempotency, event ordering... applies to all systems that require any degree of accuracy.”(“我认为大部分内容适用于通用软件工程,而不仅是金融科技...重试、幂等性、事件排序...适用于所有需要一定精度的系统。”)评论10(评分None)质疑Webhooks的普遍性:“I see webhooks documented all the time, but I have yet to use them in practice.”(“我总看到Webhooks文档,但实践中从未使用过。”)

  4. 学习资源需求:评论5(评分None)请求更多学习资源:“Does anyone have more learning resources in this field? Any model implementations, pet projects, anything to get going?”(“有人有该领域的更多学习资源吗?任何模型实现、个人项目,能让我开始的东西?”)评论12(评分None)寻求资本市场相关资源:“Anyone know of resources like this but for capital markets?”(“有人知道类似但针对资本市场的资源吗?”)

平衡性总结:评论整体认可手册的实践价值,但存在对具体建议(如金额表示、内容深度)的争议。部分观点认为内容适用于更广泛的软件工程领域,而另一些则质疑其行业针对性。