This commit is contained in:
louzefeng
2024-07-11 05:50:32 +00:00
parent bf99793fd0
commit d3828a7aee
6071 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,215 @@
<audio id="audio" title="01 | 业务初探:扫了二维码之后发生了什么?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/41/f8/4156fc9228eede2cc7ed63c674c640f8.mp3"></audio>
你好,我是任杰。今天我们进入第一个模块:金融业务及系统。
通过这个模块,我会带你了解常见的金融业务有哪些,盈利模式又是怎样的。了解了业务端的规律,我们就可以沿着这个线索推导出相应的系统核心需求以及具体组件,推测出相对应的系统设计要点。有了这些铺垫,后面我们动手去设计金融架构的时候,你的思路就会更加清晰。
金融业务有很多种,按业务模式划分,包括交易类业务和信贷类业务两种。今天是课程的第一讲,我想带你了解一个标志性的交易类业务,也就是扫码支付。
虽然扫码支付非常普遍,但是它并不简单。把这个内容安排在第一讲,我有这样三点考量:
第一,是扫码支付最具有代表性,扫码支付是现在最常见的金融场景。
第二,传统银行业务的标志性机构大多都参与到了扫码支付的过程当中,你可以通过扫码支付来了解国家金融系统的运作原理。
第三,是扫码业务同时具有互联网应用和机构应用的技术特点。扫码支付既要对接互联网用户,也要对接金融机构。你可以了解不同的架构设计思想和他们之间沟通的方式。
**总之,一旦你理解了扫码支付,也就在金融技术这个领域入了门。**现在就让我们从第三方支付出发,一起来探索扫了二维码之后发生了什么吧。
## 情景假设
扫码支付其实也分很多场景。但我们是不可能把所有的场景都讲一遍,我们在这里需要做更进一步的选择。一方面要典型,另一方面又要能给你多介绍一些参与机构。综合考虑后,我选择了与跨境电商相关的扫码跨境支付场景,具体的假设有这些:
1.付款方用户支付的是人民币。<br>
2.付款方的借记卡是国内银行A发行的简称**买家开户行**。<br>
3.第三方支付公司的备付金账户在国内银行B简称**第三方开户行**。<br>
4.收款方接受的是美元。<br>
5.收款方的借记卡是国外银行C发行的简称**卖家开户行。**<br>
6.第三方公司是通过银行D进行外币兑换业务简称**汇兑提供行**。
由于国内对人民币相关的外汇交易有管制,本外币交易需要满足一定要求,比如要求电商平台有对应的交易明细。为了方便你理解,我们假设已经在其他部分完成了相应的合规流程。
那么接下来我会分4个部分给你讲解整个支付过程用户扫码支付、第三方公司进行本币代收、外汇交易以及外币代付。
## 用户扫码
扫二维码支付显然是以用户扫码作为整个业务的起点。从终端用户的角度来看,扫码由鉴权、支付和拉取状态三个步骤组成。接下来,我们就来详细看看这几个步骤。
### 鉴权
扫码支付最终会用买家的银行卡进行支付。在你开始扫码支付之前,第三方公司需要核实你是否有这张卡的使用权,俗称“绑卡”。
那第三方公司是怎么验证用户的使用权呢在国内我们一般采用下面这4个要素来进行验证
1. 用户姓名
1. 用户身份证号码
1. 银行卡号码
1. 银行注册的手机号
这4个要素都是银行记录的信息因此虽然看起来你是在第三方支付公司的App上进行绑卡操作其实是银行在背后进行相关信息的验证工作。
由于这4个要素都是电子信息可能会被人盗用所以为了进一步增强安全性银行在验证手机号码的时候还需要验证你是否拥有这个手机号码。具体的方式是发一条验证码给在你在银行柜台办借记卡时注册的手机号码。
结合前面的内容我们可以把鉴权的过程分为4步第1步用户填写前3个要素和手机号码第2步银行发短信验证码给用户手机号第3步用户将前3个要素和短信验证码发给第三方支付公司第4步第三方支付公司再将所有信息发送给银行进行确认。
所以鉴权的过程其实是验证了5个信息其中4个是静态信息1个是动态信息。
在用户绑卡通过之后银行会返回给第三方支付公司这个用户的内部ID信息也叫Token。之后第三方支付公司就可以拿这个ID进行所有合法的操作。
刚才给你讲解的流程示意图如下:
<img src="https://static001.geekbang.org/resource/image/59/32/59bef589edd40a17ccfb71b2334b9132.png" alt="">
### 支付
鉴权完成之后,就可以扫二维码,进行支付了。二维码其实是一个图形化的字符串,背后是这笔交易对应的订单。当用户点击“确认”之后,就会开始整个支付流程。
### 拉取支付状态
那为什么需要拉取支付状态呢?我们还是从台前转到幕后,从系统功能的角度思考。
用户App的支付确认按钮是有局限的它只能确认后台是否已经收到了支付请求并不能确认支付是否已经成功。这是因为支付后台需要花一些时间和银行沟通在这个期间后台并不知道银行的支付流程进行到了哪一步。
由于不知道支付什么时候才能完成用户App需要每隔一段时间就向支付后台拉取交易情况我们通常会把这个过程叫作**轮询**。这个过程一般在几百毫秒内就能结束,所以你一般察觉不到延时。
那为什么会出现轮询这种系统对接方式呢?金融机构每天会面对大量的用户资金操作,这些操作的时间和频率有很大的偶然性。
为了应对用户操作的峰值情况,金融机构普遍通过**异步消息处理**的架构来对极端流量进行削峰填谷。如果流量突然增大,异步消息架构会缓存所有请求,慢慢处理。这样就能避免核心金融系统超载。异步消息架构的结果就是用户不会及时得到处理结果,需要自己不断地去查询处理情况。
当银行处理完支付后,银行会把支付成功的消息推送给用户和第三方支付公司。第三方支付公司也会推送给你支付成功的消息。所以你在扫码支付成功后,通常还能听到两个手机消息通知的声音。
到这里我们看到了两种不同的获取最新状态的方式。一种是用户定期去拉取状态,另一种是服务器将状态消息实时推送给用户。这种**推拉结合**的消息通知方式,其实是架构设计中常见的异步系统处理方式。支付状态获取的流程图如下:
<img src="https://static001.geekbang.org/resource/image/cc/b1/cc4e483abaf4a4b12a741fec9bb30bb1.jpg" alt="">
## 本币代收
前面我们假设了这笔支付涉及到外汇交易由于买家的和卖家使用的币种不同就无法直接转账。这时候就需要第三方支付公司这个中间人来帮忙了。中间人角色要做3件事情
1.本币代收<br>
2.外汇交易<br>
3.外币代付
我先给你说说本币代收,也就是第三方支付公司代收用户资金。通俗一点来说,本币代收就是将你该付的钱先打到第三方支付公司账上。
由于第三方支付公司的账号和买家的银行卡在两家不同的银行,本币代收需要进行跨行转账。跨行转账会涉及到整个银行系统的大小额系统和超级网银等,非常复杂。所以这里我们对场景进行一些简化,但是会和现实有一些出入,主要是方便你理解。
### 央行和清算机构
跨行转账的时候,钱是在不同的银行。因此我们想要实现跨行转账,就需要解决两个问题。**第一个问题是怎么将钱在两家银行之间转来转去,另一个问题是转的金额是多少。**
我们先看第一个问题,那就是怎么跨行搬钱。最直接的方法是用汽车将钱从一家银行的金库搬到另一家银行。但这个方法其实不太实用,汽车能运的钱重量有限,路上也不太安全。所以钱最好不要挪动地方。
这时候又需要另一个第三方机构出马了。所有银行都在这个新的第三方机构里放足够多的钱,一般叫做**存款准备金**。当两家银行之间需要转账的时候,第三方机构在内部搬运一下就好。比如美国的黄金交易所就是这种工作模式,每个客户都有自己专属的黄金仓库,很多小车在仓库之间搬运黄金。
如果这个第三方机构足够可信,那么连内部搬运都不需要。这个第三方机构只需要记录一下谁的钱有多少,以及从哪里搬了多少到另一个地方就行。信用级别最高的金融机构就是国家的中央银行,简称**央行**。**所以央行解决了真实资金的转移问题。**
我们再来看另一个问题,那就是怎么知道转移的金额有多少。会有这个问题的原因是每天银行之间的跨行交易非常多,不可能每一笔都通过央行转一次钱。所以银行系统对跨行转账的流程进行了优化。那就是在白天只做记录,不进行**任何实质性的跨行转账**。等每天结束的时候计算一下两个银行之间交易金额的差额是多少,最后通过央行进行一笔跨行转账就可以了。这种计算交易差额的方式叫做**轧差**。
这个记录白天跨行转账细节和晚上进行交易轧差的第三方机构叫作**清算机构**。你熟悉的银联及网联,以及国外的万事达,它们都是清算机构。
前面我们在介绍拉取支付状态的时候,讲过金融系统采用异步消息处理架构应对支付流量。轧差是另一种金融机构应对大流量的一种处理方式。**轧差的本质是实时消息的批量处理**,从某种程度来讲是延时更大的异步处理框架。
### 跨行转账流程
讲完央行和清算机构之后,我们就可以对跨行转账过程做一个详细的梳理了。整个过程分为七步:
第一步,第三方支付公司发送指令给**第三方开户行**,要求将钱从用户的**买家开户行**转到**第三方开户行**。
第二步,第三方支付公司拥有用户在**买家开户行**的Token所以可以合法发起这笔转账。跨行转账流程开始。
接着到了第三步,**第三方开户行**将所有信息交给清算机构。**清算机构**作为第三方负责记录这些信息,并通知**买家开户行**和**第三方开户行**记录这笔转账。
第四步,**买家开户行**记录的结果是对用户的账号进行扣款。扣款结束后用短信的方式通知用户。
然后是第五步,**第三方开户行**记录的结果是对第三方支付公司的账号进行打款。打款结束后第三方支付公司可以通过银行网页看到对公账户金额发生变化。白天的工作到此结束。此时**买家开户行**的账面上的资金虽然减少,但是减少的钱并没有实质性到达**第三方开户行**。
第六步,到了晚上,**清算机构**对白天发生的交易进行盘存,发现有一笔从**买家开户行**到**第三方开户行**的跨行转账还没有真正完成。**清算机构**会将这笔未完成的跨行转账信息发送给**央行**。
还有最后一步,**央行**收到信息之后,将**买家开户行**在央行的存款准备金调低,并将**第三方开户行**在央行的存款准备金调高。这样钱就真正地从**买家开户行**转到了**第三方开户行**。
这七步的示意图如下:<br>
<img src="https://static001.geekbang.org/resource/image/a0/44/a05832c24e6370d3096c27cb3a6f5944.png" alt="">
## 外汇交易
转账交易的第二步是第三方支付公司进行外汇交易。当第三方支付公司完成了用户的本币代扣之后,第三方支付公司账上就有了对应的人民币。接下来的一步是将这些人民币变成美元,这样才能将美元转给国外的卖家。
那么外汇交易的过程又是怎样的呢按照交易量的大小可以分为C端外汇零售业务和B端外汇批发业务两个部分。
### C端外汇零售业务
外汇交易和电商一样,也是一个买卖的过程。第三方支付公司作为中间人,需要用人民币购买美元。那美元从哪里购买呢?人民币有外汇管制,不能随意买卖,需要通过一些有特殊资质的银行才行。如果外汇不涉及到人民币,那么选择面会宽泛很多,银行、投行或者其他金融机构都可以。
账务原理建议一个账号只处理同一个币种的交易。外汇交易涉及到两个币种的货币,因此需要两个不同的账号。
在这节课的最开始,我假设了第三方支付公司是通过**汇兑提供行**进行外汇交易的。那么第三方公司需要在**汇兑提供行**里建两个账号,一个人民币账号和一个美元账号。同时,汇兑提供行内部也需要有对应两个币种的账号,一个对应着人民币资金池,另一个则是美元资金池。
所以一笔外币的购买涉及到4个账号之间的2笔支付订单。交易过程的示意图如下
<img src="https://static001.geekbang.org/resource/image/33/12/3359eb5e5b0d08c3a1cc5bb27b2ec512.png" alt="">
外汇交易完成之后,第三方支付公司在**汇兑提供行**的人民币账户金额减少,美元账户金额增加。这样第三方支付公司就有了足够的美元来支付给卖家。
我们需要注意的是,外汇交易是有成本的。第一个成本是**时间成本**。当天购买的外汇可能隔天才到账。另一个成本是**交易成本**。外汇交易一般会按照交易次数收费。因此为了节省成本,第三方支付公司通常会提前购买大量的外汇,用来应对日间的业务。只有当外汇储备下降到警戒线之后再做下一笔大额外汇的购买。
讲到这里,我们解决了第三方支付公司美元账户不足的问题,但是它用来购汇的人民币账户一直在往外出钱,总会有枯竭的一天,又该怎么办呢。
所以我们还需要考虑从外部调资金进来。由于第三方支付公司的备付金账户在**第三方开户行**,因此需要做从**第三方开户行**到**汇兑提供行**的跨行转账,示意图如下:
<img src="https://static001.geekbang.org/resource/image/75/84/75a91b3a675a8a1db40499cf2275fd84.png" alt="">
但是第三方公司在**第三方开户行**的账户也在一直出钱,我们往上推演一步,就会发现第三方开户行账户也需要有进来资金的渠道。这个是由前面我们提到的本币代收的过程实现的。我们把买家出资的流程补充完整。整个过程的示意图如下:
<img src="https://static001.geekbang.org/resource/image/0a/d3/0a01f80965bcb884cd488e1ee50712d3.png" alt="">
这样梳理下来,你是不是觉得我们已经考虑得足够全面了呢?
其实这里还有一个问题需要我们考虑:**汇兑提供行**帮助第三方支付公司实现了外汇购买。但是**汇兑提供行**的美元账户一直在出钱。那这个美元账户钱不够了怎么办?这时候**汇兑提供行**需要从其他银行寻求帮助。这个过程就涉及到了B端外汇批发交易。
### B端外汇批发业务
前面提到的电商相关的外汇交易属于外汇的零售业务。银行、投行和其他外汇提供商之间形成了一个有层级的跨国组织,专门从事外汇的批发业务。批发业务的业务量非常巨大,通常每天都有几万亿美元的规模。
外汇市场是按照交易量大小来划分层次的。最底层的是面对终端用户的外汇零售商。这些零售商负责给一般用户提供小额的外汇交易。这些小笔的外汇交易汇集在一起之后,就会形成一笔大的外汇订单,然后继续往上层交易。
和底层的外汇零售商一样,上一层的机构将所有外汇交易汇集在一起之后,形成更大的外汇订单,再往更上一层交易。
一直往上汇集这种事情不会永无止境地进行下去。这个流程的尽头是全球最大的**外汇做市商**,一般是巨型的跨国商业银行。
这些跨国商业银行面对的是全球不同国家大量的储蓄用户,所以它们手上就拥有不同币种的巨额存款。这些做市商之间通过**交换不同币种的大额固定利息存折**来实现外汇交易,从而决定最终汇率。示意图如下:
<img src="https://static001.geekbang.org/resource/image/92/fa/92c49aa31fc90f61f15a962f94ddd6fa.png" alt="">
之前我给你提到过外汇交易有时间成本,当天购买的外汇需要隔天才能到账。在这一天的时间间隔之内,外汇市场可能会有巨大的波动,从而造成金融机构账面上的资金亏损。所以,参与外汇业务的金融机构都会处理外汇相关的市场风险,比如用期货、期权等衍生品来对冲风险。这些金融衍生品,我们会在后面的章节详细展开,这里你先有个印象就行。
为了方便你理解,我们把到目前为止的流程画一个简单的示意图:
<img src="https://static001.geekbang.org/resource/image/4c/12/4c3dd63bf3be60824c525007bd270e12.png" alt="">
## 外币代付
外币代付流程和本币代收流程在原则上是一样的。不同点在于外币代付的金额是美元,流出账号是第三方支付公司的美元账号。由于卖家的账号在**卖家开户行**,第三方支付的美元账号在**汇兑提供行**,这时候需要走的是国际的清结算过程。
流程的核心思想和之前的类似,只是具体的细节会更加复杂。下图展示了简化版的支付流程。
<img src="https://static001.geekbang.org/resource/image/b5/21/b56afd2d461efef5e2757d37b6bafd21.png" alt="">
## 小结
用户在扫码支付前需要证明自己合法拥有银行卡,需要给开卡行提供**4要素**:姓名、身份证、银行卡号和手机号。验证通过后便可以开始支付流程。支付完成后用户可以通过轮询的方式**异步获取支付状态**。异步处理是金融机构应对支付流量的一种架构设计。
在第三方支付公司收到支付请求后,开始进行本币代收业务。由于账号设立的关系,需要进行跨行转账。此时清算中心和央行一起提供了跨行转账功能。跨行转账一般采用了日间交易、日终轧差结算的方式进行。轧差处理是金融机构应对支付流量的另一种架构设计。
第三方支付公司在完成本币代收业务之后,还要进行汇兑业务,具体分为外汇零售业务和批发业务。如果涉及外币代付业务,第三方支付公司还需要借助国际清结算组织的相关功能。
你需要注意的是,二维码支付涉及的大多数环节都是**异步系统**比如用户App的异步支付状态查询以及清算中心和央行及银行之间的跨行转账清结算过程。异步系统不会将结果同步返回给调用方。因此我们在设计系统的时候**就需要支持状态的查询以及状态消息的推送功能。**
本节课的知识点整体的结构图如下:<br>
<img src="https://static001.geekbang.org/resource/image/20/a9/20321d2ec6c580db82f3f6yycc756ea9.jpg" alt="">
## 思考题
第三方支付公司在做外汇交易的时候,不会只碰到单一方向的汇兑业务。既然有人民币到美元的转换,那么也会碰到美元到人民币的转换。汇兑提供商的收费只和交易数量有关,和交易币种无关。如果你是负责第三方支付公司的资金管理,你有什么方法能进一步降低汇兑成本吗?
欢迎留言和我分享你的想法。如果学了这节课让你有所收获,也欢迎把这篇文章分享给你的朋友,一起交流和讨论支付系统的问题。

View File

@@ -0,0 +1,234 @@
<audio id="audio" title="02 | 原理解读:如何理解第三方支付的业务逻辑和系统组件?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/a5/38/a5afee221222c16c8819513e3366dd38.mp3"></audio>
你好,我是任杰。这节课我们聊一聊如何理解支付业务逻辑和系统组件。
在[上一节课](https://time.geekbang.org/column/article/323701)中,我已经从宏观角度带你梳理了扫码支付从前到后的整个流程。我们发现,虽然扫码支付是一个非常便捷的用户产品,但是它后面涉及到了很多的机构和业务流程。
你有没有好奇过,第三方支付公司是怎么解决这些复杂业务问题的呢?如果你在金融行业呆过一段时间,就会发现不只是扫码支付,其他的金融业务都很复杂。那我们有没有可能复用第三方支付的这些经验,来解决其他的金融业务问题呢?
和我们解数学应用题一样,要应对第三方支付这类复杂的业务问题,我们**首先要分析它里面的核心原理是什么。接下来尝试通过核心原理来推算出可能的规律。这些规律就决定了系统架构的演进规律**。如果你掌握了这些分析问题的方法,碰到其他复杂的金融业务问题时就能游刃有余地解决了。
所以,接下来我们先搞懂支付涉及的核心金融原理,然后按照架构由简到难的顺序,逐步学习点券系统、支付系统和第三方支付公司的支付系统。这样你就能理解支付系统是如何遵循核心金融原理,一步一步从简单的几个组件发展到全面的系统架构了。
## 信息流与资金流分离
我们都知道,作为架构师,我们在做架构设计的时候,需要确保架构原理和业务原理一致。每一行都有自己独有的业务原理,支付业务也不例外。
那说到业务原理,在支付业务中最核心的概念是**信息流与资金流分离**。那什么是信息流和资金流呢?用一句话来概括,**信息流指的是想象中钱的流转过程,资金流指的是钱的实际流转过程。**
具体怎么理解呢?我给你举一个简单的例子。
假设你用户A和你的朋友用户B做生意。你的银行账户里有一块钱。白天的时候你给你朋友转了一块钱。但是你并没有把钱实际转给你朋友而是给你朋友一张字条上面记下了你转给你朋友一块钱。同样的你朋友过了一会儿也通过字条转回给了你一块钱。在白天你们俩就这么来回转来转去。
到了晚上你和你朋友对了一下白天所有的交易发现你一共要转给你朋友51元而你朋友一共需要转给你50元。
显然你们俩之间的这50元是可以互相抵消掉的。抵消之后你只需要给你朋友转一块钱就行。于是你通过银行将这一块钱转给了你朋友。过程示意图如下
<img src="https://static001.geekbang.org/resource/image/14/e5/14ba019a9b10c30e796d1cc9359bbce5.png" alt="">
我们分析一下上面这个过程。你账上的一块钱在白天的时候一直没动。这一块钱是真实的资金,你在白天的时候一直都有这一块钱的所有权。
但是在白天你和朋友通过纸条的形式将这一块钱来回转来转去,这个过程其实转移的是这一块钱的使用权。这种**资金使用权的转移过程就是信息流。**
只有晚上你们俩对完账,并通过银行转完账之后,这一块钱的所有权才真正属于你朋友。这种**资金所有权的转移过程就是资金流。**
顺便提一下,我们在前一节课介绍跨行转账时提到了清算中心和央行。这个例子中用字条转账的过程就是清算中心每天做的事情,最后通过银行转账的过程就是央行在做的事情。我在后面还会再讲一个类似的例子。
当然了,原理只是说信息流和资金流可以分离,通常这两者也是处在分离的状态。但是它们俩不一定需要分离,比如有个实时清算的概念,可以实时保证信息流和资金流一致。
现代支付系统中普遍采用了信息流和资金流分离的做法,这里的原因有很多。如果从系统架构的角度分析,我们会发现,实时清结算对软件系统的吞吐量和延时要求非常高,同时还要求所有参与的支付公司都具有实时清结算能力,任何一家达不到都不行。
这样一来,就需要整个国内和国际金融系统都重新设计系统底层的核心架构。短期来说,这么巨大的技术投资并没有相应规模的经济收益作为支撑。
所以,目前我们在支付系统架构设计中需要假设这两者是分离的。理解了这个概念,我们再来看看它会给架构设计带来哪些影响。主要有以下三点:
第一,支付环节的非银行参与者只能产生信息流,不能产生资金流。这是因为大多数金融机构并没有物理的现金,纸钞都放在了银行里。
所谓合久必分,分久必合。**虽然信息流和资金流分开了,但它们俩最终还是需要同步的**。同步的过程就需要再次和银行系统进行对接。这意味着支付系统需要**通过网关的形式与外部支付系统进行状态同步**。
第二,资金流和信息流分开之后,这两者将以不同速度在不同时间的不同主体分开流转。这意味着**支付系统从本质上是一个异步处理系统资金流和信息流的统一具有最终一致性Eventual Consistency**。这就是为什么在扫码支付状态拉取时,银行对接是异步消息处理的。这个我们上节课也提到了,你可以仔细体会一下。
第三,资金流和信息流最终需要同步,即需要一个**核算系统**来确认同步过程准确无误。
好了,讲到这里,你应该理解了支付系统架构的核心原理,就是**内部信息流系统与外部资金流系统的异步交互**。
那怎么把这个原理转化成技术架构呢?接下来我们先来看看最简单的点券系统架构是怎样的。
## 点券系统
**在点券系统里资金流和信息流是一致的**。这是金融业务最简单的情况,也是所有相关架构的基础。
顾名思义,点券系统就是管理点券的系统。因为重点是讲解架构原理,所以在这里对点券业务和系统做一些简化。
现在我们假设只有代金券这一种点券,而且你只能使用代金券来购买产品。
具体的购买流程是这样的。首先业务系统需要发起一笔交易订单用户A用10元的代金券从用户B购买一支笔。
交易订单接下来会变成支付订单。支付订单只记录了用户账号的变动关系,不包含物品交换的关系。简单来说,交易订单包括财产交换和物品交换两种信息,支付订单只包含财产交换的信息。
这笔支付订单会发给支付系统。支付系统在收到这笔支付订单后需要对用户A及用户B的代金券账号进行处理。
假设最开始用户A拥有100元代金券用户B拥有10元代金券。那么在购买后用户A的代金券账号需要减少10元的代金券同时用户B的代金券账号需要增加10元的代金券。
好了到目前为止我们可以看到支付过程至少需要3个系统
1.业务系统,负责生成交易订单和支付订单;<br>
2.支付网关,负责处理支付订单;<br>
3.账务系统,负责维护用户账户情况。
系统架构图如下:<br>
<img src="https://static001.geekbang.org/resource/image/57/dd/57d4d3e05c2907d4670716030ec390dd.jpg" alt="">
点券支付到这里就结束了。但是作为一个完整的系统好像还缺了些什么功能。比如,在用代金券支付完成后,用户可能需要检查自己的代金券余额,以及与代金券相关的账单。所以我们还需要一个**查询系统**来完成相关的查询。
另外从产品体验角度看现在的系统还有一点不足用户B并不知道自己账户收到了点券。这时候及时通知用户B可能是一个更合适的产品设计。这时还需要一个账户变动的**通知系统**。通知系统通常采用异步通知的方式。
为了方便理解,我们假设所有和用户相关的系统都在业务系统内。更新之后的架构图如下所示(红色标注的是更新的节点):
<img src="https://static001.geekbang.org/resource/image/58/fc/5864c8cf80be5eff36141e55ebb229fc.jpg" alt="">
账务系统、查询系统以及消息系统处理的都是用户的点券数据。很显然,数据传输除了上图这种基于服务的实现方式外,还可以直接通过数据库。所以在实现的时候有两种不同选择,如下图所示:
<img src="https://static001.geekbang.org/resource/image/ed/18/ed1f9b5f6e586c38eebd94ba1e633f18.png" alt="">
## 支付系统
刚才我给你讲过了信息流和资金流一致的点券系统。但现实中,绝大多数支付业务场景是资金流和信息流不一致的情况。所以你必须知道,什么样的架构系统,才能处理好信息流与资金流不一致的情况。
接下来我们来看一个典型的例子——电商公司的支付系统。
电商公司一般没有第三方支付牌照,需要通过**支付系统**来对接第三方支付公司。支付系统负责的业务种类也非常多。我们讲讲最常用的业务,通过第三方支付完成的银行卡支付。
这个例子也和前面一样用户A用10元钱从用户B那里购买一支笔。区别是这次用户A用银行卡付款而不是用点券。
在推导系统架构之前,我们照例先做业务分析。银行卡是属于用户所有的资产,电商公司没有权力处理。所以银行卡这个资产只能通过第三方支付公司进行操作(其实是通过第三方公司背后的银行及卡组织)。
另外第三方公司提供的API接口都是异步的。异步接口除了常见的成功和失败两种状态外还有第三种状态那就是**不确定状态**。这就意味着点券系统到支付系统的架构演进其实是从同步系统到异步系统的演进。
我们还是按照业务流程逐步分析看看基础的4个系统之上还缺了哪些功能需要增加哪些组件。
和点券系统一样业务系统还是照例发起一笔支付订单给支付网关用户A将银行卡上的10元转给用户B。不同点在于支付网关在收到这笔支付订单后需要判断支付系统能否独立完成资产的转移。点券这种内部资产是可以内部解决的但是银行卡属于用户是外部资产支付系统不能自主解决。
所以**支付网关还需要实现路由能力**,将内部资产和外部资产两种操作,分发给不同的资产处理组件。因此,这里我们还需要增加内部和外部资产管理系统两个组件,如下图所示。
左边是前面介绍的点券系统的架构图,你可以对比看看:
<img src="https://static001.geekbang.org/resource/image/06/a4/0663181fd1bc906f68e88ba9c39ab9a4.png" alt="">
外部资产管理系统需要对接第三方支付公司来完成银行卡转账业务。这个对接任务通过**金融网关**来实现。金融网关主要是实现二进制协议的对接,比如证书签名、加解密、协议传输、数据校验等。
通常金融网关会对接多家第三方支付公司或者银行。这样当一家支付公司临时连接不上时可以切换到下一家,或者当一家支付公司费率相对较优时可以临时切换。选择哪一家支付公司来对接的过程也叫作**路由**,通过当前情况智能选择路由的过程叫**智能路由**。因此,架构图上需要再增加一个金融网关服务:
<img src="https://static001.geekbang.org/resource/image/23/84/2398ce23cc4ecd090a15ac57f9dbd384.png" alt="">
需要注意的是,金融网关和第三方支付公司之间走的是异步通讯协议。前面讲过,异步通讯有额外的不确定状态。那架构上应该如何处理呢?
不确定状态的处理方法分为两步。第一步是在规定时间内重复查询支付状态,一般把这种行为叫作**轮询**。我们在前一节课提到的用户App通过轮询来获取支付状态这是同一个道理。
规定时间内的轮询如果失败,支付过程并不一定失败,我们还有补救的机会。每天晚上电商公司会有一个与第三方机构进行对账的机会,在这个时候双方会对白天所有交互的明细进行对比,查漏补缺。
**这就是异步系统对接时的架构设计原则,需要将同步系统的一次调用拆分成三个步骤:异步调用、轮询和对账。**
我们在这里温习一下前面讲过的信息流与资金流的分离。在电商的场景下,电商支付系统的外部资产管理系统处理的是信息流,金融网关对接的第三方支付公司处理的是资金流。信息流和资金流分离之后,两者的状态就不再一致。
**所以从信息流系统角度来看,资金流系统会存在不确定的状态,这就是为什么除了成功和失败以外,会出现第三种状态的原因。信息流和资金流虽然分开了,最终它们还是需要同步,因此需要通过轮询和对账这两种方式来实现同步。**
**这就是由支付业务原理所推导出的系统架构设计原理。**
最后我们还需要把剩下的一些关键组件补充完整。你会发现上面的架构图无法保存信息流的相关信息,所以也无法处理和资金流的同步。
信息流是通过记账方式来保存的,因此我们还要加回账务系统。这个账务系统和点券系统的账务系统功能类似,但是覆盖面不同。更新后的架构图如下:
<img src="https://static001.geekbang.org/resource/image/1a/fe/1a149ebc5f1ba4ae13350fde3becaffe.png" alt="">
其实到这里还没有结束。我们在前面提到过如果轮询失败,需要在晚上与第三方支付公司进行对账。这个对账的任务一般是由**核算系统**来完成的。除了和第三方公司进行对账之外,核算系统还需要核对账务系统与业务系统之间的一致性关系。
添加了核算系统的架构图如下:
<img src="https://static001.geekbang.org/resource/image/7b/c6/7b160549yya22143b3acefcd5d39d6c6.png" alt="">
支付系统大的架构演进到这一步,就基本上能满足电商公司常用的支付需求了。
## 第三方支付系统
最后我们来重点讲讲第三方支付系统。第三方支付系统和电商公司的支付系统的核心组件都差不多,主要是因为它们俩都不能管理实际资金,因此都是信息流的处理系统。
电商公司会通过支付系统将信息流交给第三方支付系统处理。第三方支付系统会将这个信息流再转交给银行处理。在做跨境交易的时候我们甚至还能看到不同国家第三方支付公司之间的彼此合作。
那相同的地方我就不复述了。这里我重点讲三点不同,分别是流量支持、资金池和清算系统。
### 系统的流量支持
第三方支付公司有很多家客户,有可能会面临非常大的支付流量。举个例子,比如第三方支付公司负责代发工资或者代缴水电费,一到月底就会面临非常大的流量。
除了这些可以预测的高流量外,第三方支付公司还可能会面临电商促销这种非常突然的高支付流量。所以第三方支付公司需要有能力处理这种常见的互联网应用高并发问题。
这里就是金融系统架构和互联网架构结合得非常好的地方。应对高并发场景,互联网有非常成熟的解决方案。比如我们前面提到的异步消息处理,就能削峰填谷,降低峰值流量的压力。
如果流量再高,还可以选择熔断降流等手段来进行服务降级。如果存储能力支撑不了这么高流量,还可以使用各种不同的缓存技术降低查询操作对数据库的压力,或者使用分库分表的方式来进一步降低每个数据库上面的压力。
### 备付金资金池
第三方支付公司在调用银行接口的时候会产生费用。我接下来给你讲讲如何利用**备付金资金池**减少一些交易费用,同时还能提高用户体验。
**资金池**是一种常见的用户资金管理手段。资金池就是将属于用户的钱都放在一个大的池子里。池子里的钱不分你我,你是将资金池看作一个整体来操作的。但是你还留着一个账本,上面记载了每个人原来在资金池里放了多少钱。这样虽然钱是混在一起,但是账面上是清楚的。
资金池有很大的资金挪用风险,因此金融业对资金池的设立有很严格的监管。一般有了支付牌照之后,第三方公司才可以建立用户的备付金资金池。备付金资金池是一种新的金融产品,因此也需要新的系统组件来支持。下面举两个简单的例子。
你在用第三方支付公司App的时候应该见过一种叫作余额或者钱包的东西。你可以将银行卡里的钱转到余额账户。之后就可以直接使用余额里的钱。但是第三方支付公司并不一定会将你和我的余额分开存储很有可能是放在一个资金池里处理。
比如下图展示了一种资金池的管理方式。ABCD四个用户在第三方支付公司都有自己的余额账户。但是这4个余额账户并不是实际存在的只是4个虚拟账户而已。真正的钱其实还是存在第三方支付公司在银行的账号里。
<img src="https://static001.geekbang.org/resource/image/be/25/be88d0a71c6f72500091a641157e5b25.jpg" alt="">
第二个例子是第一个例子的升级版。我们在上一节课说过外汇市场是一个一个有层级的市场。资金池也一样,多个资金池也可以拼成一个更大的资金池。于是第三方支付公司可以在多家银行开设很多资金池账户,所有这些资金池账户的钱形成更大的资金池(监管机构正在逐步限制这种行为)。
当把资金池分散在多家银行之后,第三方支付公司就不再受制于单独某家银行。这样就可以利用不同银行的费率情况来进一步降低运营成本。
举个例子,比如跨行转账需要多家银行之间配合,还可能需要支付一定的跨行交易费用。但是如果第三方支付公司在每家银行都有资金池,就可以直接在两家银行内部完成用户资金和资金池资金之间的操作了。
利用资金池来优化跨行转账的例子也有升级版。在进行跨境贸易的时候也可以使用多个资金池来降低交易成本,但这不是主要原因。跨境转账一个不太友好的问题是时间非常久,需要好几天才能到账。这时候如果你在每家银行都有资金池账号,跨境转账问题就变成多个银行内部转账的问题了,这样就能实时到账,大幅提升用户体验。
备付金资金池要求账务系统有层级式的账户体系,并且有相应的账户和资金操作。升级版的资金池看起来是下图这个样子:
<img src="https://static001.geekbang.org/resource/image/31/c7/3164a667b2cebc2c1dfcd9a6fc3cd8c7.png" alt="">
### 清结算能力
清结算中心处理的是多家银行之间的跨行转账。当第三方支付公司有了多个资金池之后,这些资金池之间的转账关系其实和跨行转账一样。既然是一样的,那么第三方支付公司有没有可能做一些清算公司的事情,从而进一步降低交易成本呢?
的确如此。所以成熟的第三方支付公司内部都会有一个自己的清算中心。这个清算中心把自己当作一个外人,对资金池之间的转账交易进行清结算工作。这里要注意清算中心的**结算过程涉及到资金流操作**,需要通过内部支付网关来操作外部资金。
这样我们就把第三方支付公司最后一个组件补完了。现在的架构图如下:
<img src="https://static001.geekbang.org/resource/image/8a/96/8af65eca509df8c3e97171a0206ce096.png" alt="">
跨银行备付金和清算中心合在一起后,第三方支付机构就具备了跨行清算的能力。由于这种业务模式不容易监管,容易出现洗钱等非法行为,国家已经逐步取消了这种资金管理模式。
但是清算中心这个组件还是保留了下来。尽管不能再进行跨行清算,不过有了清算中心之后就有了清算的概念,这让一些常见的内部信息流和资金流处理的方式变得更加清晰。
这个例子告诉我们,由于监管条例在不断完善,支付业务和系统架构也要随之改变。比如你在欧洲从事第三方支付业务的时候,很有可能会碰到欧盟制定的“通用数据保护条例”,这就要求你对系统架构的信息存储做进一步的划分。因此我们在设计支付系统的时候,需要根据当时当地的监管条例合理选择架构。
## 总结
这节课我们一起梳理了支付业务逻辑最终推导出C端支付核心组件。
C端支付需要解决的**核心问题是信息流与资金流分离。**我们先分析了最简单的点券系统,这种系统信息流与资金流不分离。点券系统需要账务系统来对点券这种资产进行管理,用户需要通过支付网关来对接点券系统。
那资金流与信息流分离的系统又是啥样的呢?电商的支付系统就很有启发性。点券系统需要处理的同步消息,支付系统则需要处理异步消息。所以支付系统除了需要复用点券系统的核心组件外,还需要核算系统来保证异步消息的正确处理。
有了前面的基础,再去分析第三方支付系统的核心组件就很容易了。第三方支付在业务上需要用资金池来降低业务成本,因此在架构上需要有核心组件来对资金池进行操作,同时也需要用清算中心来简化资金池操作的优化管理。
这节课的知识点整体的结构图如下:
<img src="https://static001.geekbang.org/resource/image/f6/f4/f6d7505c9130494yyd60753cfcee4df4.jpg" alt="">
## 思考题
现在跨境电商越来越普遍了。通过跨境电商,一位中国买家可以购买一支在美国销售的铅笔,这时买家付的是人民币,但是卖家收到的却是美元。
假设支持外汇业务的第三方支付公司自己拥有大量的人民币和美元储备,可以在外汇支付过程中充当买家和买家共同的对手方,即买家的人民币支付给电商公司,随即电商公司把自己拥有的美元支付给卖家。
那么为了支持外汇业务,支付公司的架构应该怎么做调整呢?
欢迎留言和我分享你的想法,也欢迎你把这篇文章分享给你的朋友,一起交流和讨论支付系统的问题。

View File

@@ -0,0 +1,163 @@
<audio id="audio" title="03 | 产品大观:不同金融业务都有哪些技术实现要点?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/da/88/dae16a21e83d06a3693472a71b7b1d88.mp3"></audio>
你好,我是任杰。这节课我和你聊一聊不同的金融业务都有哪些技术实现要点。
和前两节课一样,在聊技术之前我们先聊一聊业务。提到金融,你可能第一个想到的是金融行业很赚钱。金融行业赚钱的方法有很多种,但是最核心的原理只有一个,那就是**利用信息不对称赚钱**。
信息有很多不对称的方式,用到的系统工具也都不一样。所以接下来我会带你了解常见的金融业务以及它们需要的技术,你了解了这些典型案例之后,无论再碰到多困难的金融问题,都能做到胸有成竹,游刃有余了。
## 信贷类业务
### 传统信贷业务
我们先来说一说最常见的信贷类金融业务。信贷业务俗称放贷传统的银行主要从事的就是这个业务。信贷类业务的表现形式有很多比如有面向企业的贷款或者给你的房贷以及P2P、花呗、借呗、白条等等。
那信贷类业务利用了哪些信息不对称来挣钱呢?
比如说你的公司需要一大笔临时贷款来买原材料,但是资金量太大,找不到人借给你。但是世界上可能有一位有钱人,他手上有一大笔钱,却一直都贷不出去,没有办法增值。
这时候银行作为中介机构就站了出来。有钱人把手上的钱用低的利息存进银行,银行马上转手把钱用高的利息贷款给你。通过**将利息低买高卖**,银行就能“躺着赚钱”了。下面这幅图展示了银行通过信贷业务赚钱的过程:
<img src="https://static001.geekbang.org/resource/image/85/59/853d0d4756d4f931e369f6bf3cf17159.jpg" alt="">
你应该知道贷款是有可能出现**违约**的。一旦违约,银行亏的就不仅仅是利息,还包括所有本金。**违约表示银行对还款人的个人或者公司信息了解还不全面,也是一种信息不对称**。
银行需要解决这个信息不对称问题来防止亏欠。毕竟不亏钱就是赚钱。所以传统银行需要通过收集数据来评价借款人的**还款能力**,也就是借款人的**信用评级**。很长时间以来,银行的信用评级过程主要还是依靠信贷员对借款方的熟悉程度。
所以,这种传统银行信贷业务买卖利息的操作,其实对信息系统的要求不高。它只要求结果正确,对时间和吞吐量都没有什么要求,信息技术并不是传统信贷业务的核心竞争力。
不过这一点因为互联网和大数据的出现而发生了改变。有了互联网和大数据,银行就能快速全面而且低成本地了解借款方的情况。你平时在电商网站上的各种消费,玩游戏时充的点券,以及出行旅游的地点和酒店级别,都可以用来描述你的还款能力。
这时候信贷行业的核心竞争力变成了怎么才能更好地收集和处理数据。这就是大数据能发挥价值的地方。
对于系统架构来说,**信贷业务的特点是交易频率低,而且用户评级在短时间内不会发生大的变化,因此整个系统架构不需要实时组件,常用的批处理、大数据处理框架都能很好地发挥作用。**
当然了,如果你想要提高用户体验,给用户一种实时放款的感觉,系统可以提前算好用户的信用评级。你经常见到的各种信用分就是这个提前计算的结果。
### 次贷危机后的信贷业务
你有没有想过,你的银行定息存折是可以抵押给银行,然后再贷款的呢?这个过程就是**资产证券化**。
2008年发生的次贷危机就是用个人的房贷来抵押贷款。简单的抵押赚不了多少钱所以有一些聪明人把一大堆房贷打个大包然后按照信用评级拆分成几个小包。类似的小包还可以堆在一起然后再继续拆分。最后再将拆分好的小包卖给投资人。
这时候奇迹出现了,如果按照数学公式来计算,房贷总量虽然没变,但是分分拆拆之后总价值反而增加了很多,这样金融公司就能躺着赚钱了。下面这幅图是次贷将资产打包拆分的示意图:
<img src="https://static001.geekbang.org/resource/image/4c/56/4cb4c33c4ed71c013181f89f9b49d056.jpg" alt="">
现在常见的P2P、花呗、借呗和白条等背后大多都是这种资本运作方式只不过它们将资产证券化的资产从房贷换成了个人消费贷。那这种资产证券化的金融业务对信息系统有什么要求呢
这里我们需要了解一些必需的金融数学原理。我们在前面提到过贷款可能违约,这个违约的大小是用信用评级来衡量的。所以**违约率其实是一个数学上的概率**。把不同资产放在一起,**打包后再拆分的过程,从数学上来看就是用一组随机变量生成一个新的随机变量**。
你应该听过次贷危机产生的原因其实是区域性的房贷违约,这意味着从概率上来讲房贷**违约率之间有很强的相关性**。这些相关性让最后生成的新随机变量的计算公式变得非常复杂。
这意味着资产证券化的定价过程对系统有两个挑战。
**一个挑战是计算复杂。**数学公式有可能一页纸都写不下,那么开发人员怎么正确实现就是一个很困难的问题。就算你觉得自己实现的是正确的,那你又怎么证明呢?我们会在第二个模块“系统的正确性保障”里给你详细讲讲如何保证计算的正确性,这里你先有个印象就行。
**另一个挑战是数据量大。**资产证券化到一定程度之后就算不出来数学公式了,只能通过暴力求解的方式来穷举所有可能的场景。这可能是一个天文数字,所以需要成千上万台机器同时计算才能及时算出来。这就涉及到如何保证分布式计算的正确性。我们在第三个模块“分布式正确性及高可用”中还会详细展开。
## 交易类业务
前面讲的信贷类业务,主要还是由传统银行来完成,对信息技术的应用比较有限。金融行业也是有很多高科技的,它们主要体现在投资银行和其他新兴金融机构身上。它们多半从事着另一个大的业务,也就是交易类业务。
交易类业务其实是一个非常巨大的隐形的金融市场,一般人很难了解全貌。那我们就来看看典型的交易类业务都有哪些。
### 场内交易
我们先来看看最常见的交易类业务。就算你没有买过股票,也应该听过**股票交易所**这个金融机构。**在交易所内的交易叫作场内交易,交易的场所就是交易所**。
**交易所角度**
很多企业家定义自己是否成功,就是看公司能不能**上市**。上市指这家公司的股票可以在股票交易所内交易。稍微学术一点来说,上市就是股票在**二级市场**交易。
既然有二级市场,那么肯定还有一个**一级市场**。一级市场其实就是公司股东之间的私下交易。
**一级市场的信息不对称主要体现在如何匹配大额股票的买家和卖家。投资银行解决信息不对称的方式是通过公司和自己的人脉来撮合买卖双方。由于解决方案是靠人而不是靠技术,所以这一阶段对信息系统要求不高**
就算投资银行撮合了一级市场的买卖双方,依然还有信息不对称的情况,那就是股票的真正价值是多少?
你学过金融理论的话就会知道,**公开交易市场能发现合理的价格信息。所以为了解决价格信息不对称的问题,投资银行会帮助客户公司将股票在流动性高的二级市场上销售。由于二级市场是个公开市场,靠大量的交易来解决价格信息不对称问题,而不是靠人脉关系。这时候就对信息系统有很高的要求**。
信息沟通得越快,就越能发现资产的合理价格。所以股票交易强调交易的速度,也就是系统延时。对开发人员来说,**股票交易所是一个秒杀系统**。只不过和电商秒杀的区别在于股票交易所每时每刻都在秒杀。所以**股票交易所需要有一个极低延时、极高吞吐量的系统架构**。
**交易所技术**
你如果参与过互联网应用的开发的话,应该了解很多互联网行业用来对付高流量的解决方案,比如分库分表、缓存、最终一致性等等。遗憾的是,这些**互联网方案都是靠牺牲延时来换取流量**。对于股票交易所来说,高延时是完全不可以接受的。
从事过开发工作的人都知道软件处理很难实现**微秒级延时**,就算达到这个延时了系统吞吐量也上不去。但是股票交易所确确实实既有低延时,又有高吞吐量。那它是怎么做到的呢?
答案很简单,就是**用硬件**,比如用**FPGA**来实现。理论上硬件能实现和所有软件一样的功能,但是**硬件研发成本高,而且非常耗时**。股票交易所恰好不怕这些问题。**交易所别的没有,就是钱多**,所以只要投资回报比足够,再多的钱都能拿出来。而研发时间久在交易所里问题也不大,主要是因为**交易所业务逻辑非常简单**。
交易所的主要功能是撮合买方和卖方。交易所在系统内维护了还没有成交的卖方订单和买方订单。当一个新的订单进来的时候,交易所会查看能不能成交。如果不能成交就等待下一笔订单。这个撮合逻辑非常简单直白,示意图如下:
<img src="https://static001.geekbang.org/resource/image/8f/2b/8f3a4c1238090a2c290f6aa7b3ff902b.jpg" alt="">
**交易所用户角度**
股票上市之后依然存在信息不对称的问题。有一些金融机构会故意增加信息不对称,而另一些金融机构则在努力发现和消除这些信息不对称。那背后又有哪些故事呢?
如果你和我一样是个股票小散户的话,在股市上是掀不起多大风浪的。但是如果你掌管了一家大型机构,机构里每次买卖都是上亿的资金,那很有可能会影响到市场价格。而且通常是负面影响,也就是说会让你买得更贵,或者卖得更便宜。那怎样才能避免这种情况呢?
这时候,投资银行或者券商会给你提供一个**拆单**的服务。他们会将你的大订单拆成很多小订单,并且选择在不同的时间发送到股票交易所,这样就不会产生剧烈的市场波动。这意味着**投资银行需要有一个算法交易平台**。这个平台需要实时对市场数据进行分析,用算法来拆解和执行订单。
拆单服务的本质是造成信息不对称。一般用户无法获取你正在大量交易股票这个信息。前面提到过,金融机构是靠信息不对称赚钱。既然投资银行赚钱的方式是通过信息技术来造成信息不对称,那么有没有可能通过消除这些信息不对称来赚钱呢?
**做高频交易的对冲基金**就是一类通过发现和消除信息不对称来赚钱的金融机构。他们的核心竞争力就是极低的系统延时。**当延时高的时候,股票体现的是宏观规律**,比如你会看公司的基本面,或者猜是不是庄家在出货。但是**当延时低的时候,股票体现的是统计规律**。
比如前面提到的将股票拆单的操作。如果你发现了一个小的买单,那么接下来很有可能会有很多小的买单。如果你系统的延时足够低,就可以挤在这些小单的前面买入,然后马上卖出,从而通过超短线操作获利。所以**高频交易系统里也有算法交易平台**。这个平台也需要以极低的延时来分析实时市场数据,并且也要以极低的延时来执行订单。
讲到这里你会发现,交易所的机构和用户之间互相在玩猫鼠游戏,谁的系统速度快,谁就更有可能发现赚钱的先机。所以交易所相关的金融机构对系统要求非常高,一些极其领先的软硬件技术在这里都能找到身影,这也是为什么大型金融机构都说自己是高科技公司。
**交易所用户技术**
交易所用户都很关心系统延时。那么延时究竟需要有多低呢?一般来说,**机构用户要求系统的消息处理时间在毫秒和微秒之间**1/10001/1000000秒。那这么低的延时会怎么影响系统架构呢
首先影响的是**编程语言的选择**。一般来说C是首选核心代码用汇编语言实现。要求不高的地方用C++也可以。至于互联网常见的编程语言比如Java、Go、Python、JavaScript等都不适合。
其次影响了**软件架构**,这也是金融软件和互联网软件架构的最大不同。
互联网软件通常会使用SOA或微服务架构。这种架构导致业务的调用链很长每次调用都有网络延时。
交易所用户架构则完全相反。**系统会用单个进程来完成所有的事情,最好不要有网络开销**。如果交易所允许,金融公司还会出钱将机器放在交易所的机房内。这样就能进一步缩短光的传输距离,节省宝贵的数据传输时间。
当然了,由于种种原因,目前国内的交易所和券商在信息技术这一块还没有毫秒级以下的需求。但是随着金融系统的逐步开放,外资金融机构会带着这些成熟的技术来和我们竞争。软件技术的成熟需要一定的时间积累,我们需要做到笨鸟先飞,提前做好技术布局。
### 场外交易
股票市场和其它的场内交易只是金融市场的冰山一角。**绝大部分的金融交易都发生在交易所外,也叫场外交易**。
**金融产品**
场外交易的金融产品类型非常广。如果你想**私下交易股票**,这个行为也属于场外交易。**外汇交易**虽然和股票市场类似,但是外汇交易没有交易所,也属于场外交易。你平时听过的**花呗、借呗、白条、P2P、供应链金融等一旦它们被资产证券化也属于场外交易**。那这些场外交易产品,它们对于信息系统又有什么要求呢?
**合同定价与市场风险计算**
前面提到过,交易所的一个功能是发现价格。人们通过在公开市场交易来消除价格信息的不对称。那场外交易没有交易所,又该怎么发现价格呢?
既然你在场外交易的时候没法被动地发现价格,那么就只能**主动发现价格了**。所以对于场外交易的金融产品来说,你需要独立计算出合同的价格。
前面学习资产证券化的定价过程时,我和你说过,定价系统需要处理复杂度和数据量的问题,这一点也是对所有场外交易定价系统的要求。但资产证券化只是一种场外交易的金融产品,金融行业还有很多其它的金融产品,不同的产品定价方式完全不一样,那时间长了怎么解决定价系统数量多的问题呢?
幸运的是,**所有场外交易的金融产品都存在共性**,比如说它们肯定都跟钱有关。这些共性可以进一步提炼出来,从而有希望搭建一个金融产品的统一定价平台。这个抽象总结的方法就是**领域驱动设计,**我会在[第4](https://time.geekbang.org/column/article/325378)、[第5节课](https://time.geekbang.org/column/article/327137)里给你详细解读。
## 小结
这节课我给你讲了不同的金融业务都有哪些技术实现要点。
传统的银行主要处理的是放贷业务,在很长一段时间不需要信息技术的帮助。但是信息技术的崛起不仅提高了**用户信用评级的准确度**,成本还很低。这时候的信息系统需要具备批处理计算的能力。
2008年次贷危机之后人们学会了如何复制次贷这种金融模式衍生出了很多信贷类的资产证券化产品。这些产品要求系统能解决复杂度和数据量的问题。
除了信贷类业务,还有一类业务是交易类业务。交易类业务可以分成场内和场外两种交易模式。
股票交易所是一种常见的场内交易模式。对于股票交易所来说,信息系统需要解决极低延时,极高吞吐量的交易问题。股票交易所的用户对速度和吞吐量也有同样的要求。但是他们彼此之间会互相竞争,需要用算法交易平台来发现彼此的赚钱机会。这对编程语言和架构的选择都带来了很大的影响。
场外交易的金融产品类型众多,因此需要用到领域驱动设计的方法论来降低定价系统的复杂度。
<img src="https://static001.geekbang.org/resource/image/b8/d2/b8ccf0e5446a9ff0fdc6e25f5925c7d2.jpg" alt="">
## 思考题
在上世纪中期的美国银行的定义是吸纳存款并且发放贷款。一旦一家金融机构被定性成为了银行就需要接受美联储监管。监管会限制金融机构的行为因此金融机构并不一定愿意成为银行。那么如果你是一家银行的CEO既不想被定性成银行又想做一些银行的事情你准备做怎样的业务调整呢
欢迎留言和我分享你的想法。如果学完这节课你有所收获,也欢迎你分享给你的朋友,一起交流和讨论。

View File

@@ -0,0 +1,235 @@
<audio id="audio" title="04 | 领域驱动设计(上):如何设计金融软件顶层架构?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e0/25/e0ebc096b7d6daf64ab3f16028f6b025.mp3"></audio>
你好,我是任杰。这节课我想和你聊一聊如何设计顶层金融软件架构。
通过前面三节课的学习,你应该感觉到金融业务比较复杂,对应的金融软件也很复杂。那想让业务和架构设计良好配合,就是一个非常有挑战性的事情了。这也是软件工程要解决的问题。
软件工程的教材里一般不会写项目怎么成功,而是记录项目怎么失败。金融行业对信息化要求很高,那在实际解决问题时,金融行业自然也会经历很多失败的软件项目。
幸运的是,错的次数多了也渐渐总结出一些比较好的方法论,本世纪初出现的**领域驱动设计**就是其中一个。一些大型的金融公司已经用这个方法,从战略上重新设计了顶层框架和运作机制,也取得了不错的效果。
想更好地掌握这种方法,你就要搞清楚它的适用范围以及整体思路,这样才能在后续实践中更好地使用。话不多说,接下来我会从三个角度入手,带你理解领域驱动设计理论中的核心知识点。
## 领域驱动设计侧重点
顾名思义,领域驱动设计(**Domain Driven Design**,简称 **DDD**)指的是针对特定领域进行定制化的设计。
从**空间**上来讲,它看到的是整个行业或者整个领域。从**时间**上来讲,它看到的是软件从发生、发展到消亡的整个生命周期。从**角色**上来讲,它看到的是业务、产品、开发和运维等所有参与人员的合作。
因此领域驱动设计是战略上的思路,而不是战术上的实操。这里你要抓住一个重点,**领域驱动设计解决的是复杂问题。**
虽然领域驱动设计是从宏观角度解决问题,但是它非常务实,主要体现在以下两个方面,一方面是**注重投资回报比**Return On InvestmentROI另一方面是**做长期优化**。
### 注重投资回报比
我们想做好领域驱动设计,需要多角度思考问题,还需要对各方面因素做一些平衡,所以这个设计本身是一个非常耗时耗力的过程。
如果你投入了大量的人力物力和时间,却没有收到相应的成果,就有点得不偿失了。这种情况下就不推荐使用领域驱动设计了。
具体来说,适合使用领域驱动设计的系统需要具备这些特点:
1.系统组件足够多。<br>
2.业务逻辑足够复杂。<br>
3.软件生命周期长。
总之一句话,简单问题不要用领域驱动设计。金融软件恰好满足了上面三个要求,因此它也是一个领域驱动设计的标志性应用场景。
### 长期优化
你也许听过一些国外的真实故事,讲的是金融系统完成开发之后,毫无问题地运行了几十年。当它突然出了问题时,还需要把早已经退休的开发人员反聘回来解决。
这些故事告诉我们,金融系统可能会存在很久,可能所有最初的相关人员都已经去做其他项目了,这个系统还需要有人继续维护。
这说明软件的生命周期可能超过个人的项目周期。如果维护的人换了,就有可能出现经验知识的传承问题。领域驱动设计尝试解决这些长期沟通问题,降低整个软件生命周期中的沟通成本,这样就能降低项目失败的可能性。
了解了这两个重点之后,我们还要搞清楚具体应该怎么做。
我们在解决问题的时候一般顺序是先搞定人,再做事。所以接下来我们先看看怎么设计人员组织架构,然后再考虑怎么设计系统组织架构。
## 人员组织架构
我们都知道,软件开发过程中涉及到三类人,第一类是业务方;第二类就是系统分析人员,包括产品经理和架构师;还有一类是系统开发人员。
相应地软件开发流程有4个步骤估计你也不陌生
1.业务方提出需求。<br>
2.产品经理分析需求。<br>
3.架构师根据产品经理的分析做出合理的架构设计。<br>
4.开发人员按照产品文档和架构设计文档来进行开发。
开发流程示意图如下:
<img src="https://static001.geekbang.org/resource/image/4a/7c/4a91200628b8caf270ce8a4926c75e7c.jpg" alt="">
这个流程看上去很好,但是在实际操作中会有一些问题。比如当开发人员发现文档细节不够全面,甚至内容有误怎么办呢?这时候,沟通只能原路返回,等产品或者业务方再次确定清楚后,再从上往下传递消息。
我们尝试从宏观角度分析这个沟通问题。软件开发过程中不同角色之间的沟通,其实是一个内容翻译的过程。由于每一步沟通都会造成信息损失,沟通的流程越长,信息损失越大。
那怎么解决沟通中的信息丢失问题呢?领域驱动模型提了一个根本的解决方案。既然沟通的流程长了会丢失信息,那么最优化的沟通方式不就是只有一个层级的沟通吗?
所以领域驱动设计取消了常见的垂直沟通方式,变成小组沟通方式。**每次沟通都是所有相关人员参与。**下图列出了这两种不同的沟通方式:
<img src="https://static001.geekbang.org/resource/image/03/f5/03a52cf0ee15229bea0539a536338bf5.jpg" alt="">
表面上这只是沟通方式上的一点小小的改变,但其实是一个**文化的转变**,时间长了会带来一些根本性的变化。
第一个变化是**提高了决策的速度。**在小组沟通的模式下,问题能直接从发现的人手上交给解决问题的人,不再需要层层分析,层层审批。
第二个变化是**打破了部门壁垒。**我们在开篇提到了领域驱动设计需要有一定的业务复杂度。复杂业务会有自己独有的专业术语。
金融行业充满了生僻的术语比如说中文的有融资融券、内保外贷、永续债券等等英文的有DCF、long/short、cap/floor、Snowball、Butterfly等等。不知道这些术语你都了解多少。开发人员想要正确地进行系统建模前提就是先对这些术语有正确的了解。
那怎样才能了解呢?答案很简单,就是**直接参与。**开发人员需要直接和业务方沟通,甚至直接参与业务。同样,业务方也很难理解开发人员的术语,也需要通过直接沟通来了解一些基本的行业逻辑和假设。
这个沟通过程中,会沉淀下来对专业术语的共同理解,这就是**领域语言**Domain Language。有了领域语言之后各方的沟通再也不是鸡同鸭讲而是永远在一个频道上。
第三个变化是**弱化了产品经理的角色。**产品经理负责收集业务问题,分析后将需求交给开发人员。那问题来了。谁对业务最了解呢?在金融行业,开发人员才是最了解金融业务的人。这一点可能会超出你的想象,但是事实如此。
金融行业讲究细节,每一个犄角旮旯的情况都要考虑清楚。开发人员在写程序的过程中,需要对金融业务的正常和异常情况进行极为完整的分析,所以不得不深入了解金融业务。这也是为什么在一些大型的金融公司里很少有产品经理这个岗位。
总结一下:**领域驱动设计建议软件的所有参与方之间能以小组的形式进行直接沟通。开发要懂业务,业务方和产品也要懂技术。沟通的结果是形成一个大家都能认同和理解的领域语言。**
## 系统组织架构
人的问题解决了,我们再来看看怎么解决事情。当你接手了一个复杂问题,第一步不是想怎么去解决它,而是应该仔细分析它为什么复杂,复杂在什么地方。
经验告诉我们,一个复杂的软件系统也不是所有地方都复杂,各个组件的复杂度和重要程度都不一样。所以我们可以像庖丁解牛一样,对系统组件进行分解,然后把相同的归类,统一对待。
**领域驱动设计提供了一个分解问题的思路。**领域驱动设计将所有业务领域划分为三大类型:**核心领域、通用领域以及支持型领域。**不同领域有不同的处理态度。那我们来逐一讲解一下每个类型的划分标准。
### 核心领域
金融系统软件有一个特点是所有组件看起来都很重要,就连最基本的短信通知功能都不能出问题。这就是我们之前提过的,只要是和钱相关的都是大事情。
但是你明显能感觉到,组件之间的重要性还是有微妙的区别。比如说,同样是对外发消息的网关组件,券商对接交易所的网关明显比短信通知网关更重要。那你的这种“感觉”究竟是从哪里来的呢?
**一个软件组件是否重要,这取决于它所属的业务是不是核心业务。而业务是不是核心又取决于竞争对手**。从整个金融行业的角度来看,一家金融公司如果能存活下来,一定需要有比其它类似金融公司做得更好的地方,也就是它的竞争优势。
举个例子。上世纪70年代股票交易量大增。当时一台大型计算机的价格简直就是天价。一些有远见的金融公司花了巨额资金买了这些计算机来处理股票交易记录。
很快,没这么做的人就因为无法处理大量交易而淡出市场。他们退出不是因为业务方向错误,而是因为在没有计算机辅助的情况下,服务质量下降。这时候的金融行业的核心竞争力就是电算化,股票交易处理就是核心业务领域,交易清结算组件就是核心组件。
到了21世纪初衍生品定价模型逐渐成熟了谁计算金融风险的速度越快结果越准确谁的盈利就会越高。
在08年经济危机的时候有的金融公司计算风险的速度快就能提前逃离市场。如果你计算得慢就得被迫吞下有毒资产。这时候的金融行业的竞争优势就是风险的计算和对冲风险计算就是核心业务领域风险计算组件就是核心组件。
所以,你可以这样理解,**一个业务是否是核心业务,取决于它是否能给公司带来行业内的竞争优势。**
我结合自己的经验,给你梳理了核心领域的三个要点,分别是资源分配、审时度势以及宏观视角。
**资源分配**
核心竞争力是买不来的。所以核心领域所对应的软件组件一般建议自研。同时我建议你把公司最好的人手放在核心领域的开发项目组中,这就是好钢用在刀刃上。
另外,由于核心竞争力需要不断升级,你还要做好长期维护的准备。我们开头说过,领域驱动设计的一个侧重点是投资回报比。核心领域是重要的赢利点,所以它需要有足够的时间和资源投资来保证未来的竞争优势。
**审时度势**
金融行业的玩家都是聪明人,所以一家公司的核心竞争力是瞒不住的。稍微过段时间就会有人学会你的赚钱之道,这时候你们之间的竞争就变成了公平竞争,你就再也没有核心竞争力了。
还是举之前金融市场的例子。在上世纪70年代计算机处理订单是一家金融公司的核心竞争力。但是很快人们发现只要用了电脑就可以有类似的服务质量。金融公司最不缺的就是钱所以它们很快也都对业务做了更新换代用电脑替代人工操作。
这时候金融行业的核心竞争力又变成了怎么用计算机的速度来赚钱。
过了40年到了08年金融危机的时候有的金融公司靠着超前的风险计算能力躲过了危机。很快怎么复制这种计算方法不再神秘这时核心竞争力就变成了谁能最快地上线风控模型以及谁的计算成本最低。
所以在金融行业,我们想判断核心领域,就需要合理判断此时此刻公司所处的行业位置,在可预见的未来对手会如何应对,以及自己应该如何针对性地升级业务和系统。
**宏观视角**
每家公司的核心竞争力都不相同,所以一家公司的核心领域可能对其它公司来说并不是核心。比如,尽管同属于金融行业,券商的会计系统不是最核心的领域,但是对于一家提供会计服务的公司来说,会计系统是它最核心的领域。
所以核心组件不能根据其内容来一刀切,而是要根据它属于哪一个更大的环境,再来做灵活判断。
那怎么宏观地判断一个核心领域呢?这就要看它能不能给你带来**超额利润**。超额利润是一个经济学的名词,表示超出一般行业水平的利润。比如对券商来说,能不能发短信通知给用户其实对盈利水平的影响不大。但是如果能提高用户下单的速度,那就完全不一样了。
### 通用领域
顾名思义,通用领域是可以在不同行业通用的领域。比如我们前面提到的短信平台,不只是金融公司可以使用,物流公司也可以使用。类似的还有安全、日志、存储等等。
既然是通用领域,那么市场上一定会有多个类似的产品,而且也会存在第三方服务提供商。领域驱动设计强调投资回报比,**所以当市场上存在多个类似的产品的话,我们要尽量采购相关服务或者产品,而不是自己研发。**
道理很简单。同一件事情如果做的次数越多,质量就会越好,成本也会更低。所以相比自己做,通用领域选择第三方服务提供商的性价比更高。
当然了,有些情况下我们会发现通用领域也不是完全通用的,在一些细小的地方不能完全满足要求。如果你找不到完全符合自己需求的产品,就争取只做二次开发。如果二次开发也不行,一定需要投入研发力量,那么尽量投入一些非核心开发力量,比如外包团队或者非资深开发人员。
同时你也不要对软件质量做过多的要求。这时候要**本着能用就行的心态**,研发系统的时候也按**随时能替换**的方式去设计。
### 支持型领域
支撑型领域是那些用来辅助核心领域正常运行的领域。支持型领域并非核心竞争力,但是缺了之后也无法正常开展业务。比如说会计系统、市场数据系统等等,一般属于支持型领域。
支持型领域和通用领域很容易搞混。支持型领域一般并不会跨行业通用,顶多只在金融行业内通用。
比如对一家做聊天论坛的公司来说,一个股票数据分析系统并没有多大帮助。因为支持型领域通用程度不大,它们的共性就会更小,因此更难找到可以替代的解决方案。
如果你确定了某个系统是支持型领域那么你可以按照这3个步骤来考虑
1.和通用领域类似,首先考虑购买第三方软件。
2.**如果市场上没有合适的产品,考虑能否人工处理。**比如一些简单的会计科目处理或者市场数据处理,用办公软件就能达到很好的效果。金融公司不是互联网公司,只要能赚钱就行,不需要为了面子而投入稀缺的软件开发力量。
3.如果我们一定需要自研,要和对待通用领域的态度一样,能用就行,保持**和核心领域低耦合**,随时准备替换。
### 领域分析举例
我们讲完了怎么做领域分析之后,你一定想知道怎么分析一个实际的例子。
假设你有一天成为了有钱人,需要有人帮你打点一下财产。这时候金融公司会给你提供**资管服务**,替你理财。理财产品有很多种,其中资产数量最大、收益最高、风险也最高的一类是衍生品。在这里我们看看衍生品管理系统应该怎么分析。
理财产品的管理分两步。先要购买合适的金融产品,也叫交易前,或者**投前**。买好之后就需要管理,在合适的时候买进卖出。这一步也叫交易后,或者**投后**。我们先来看看投前的过程涉及到的系统应该怎么分析。
首先,你需要在系统中记录有兴趣购买的衍生品。因为衍生品是一种有完整生命周期的金融合同,所以系统需要有一个金融合同的**生命周期管理系统**。
其次,你在挑选金融产品的时候需要知道这个产品的价格,如果价格低就买。这就是定价和报价环节。这个环节开始的时候,你需要对合同价格有自己的判断,这就要用到**定价系统**。
接着就到了合同签订和打印的步骤。金融合同的签订其实是一个交易过程,就需要有**交易系统**。
衍生品交易涉及到的金额特别巨大,因此很多人都不太信任电子合同。合同签订之后还需要打印存档,这就需要有**打印系统**。
投前的步骤在合同确认之后就结束了。接下来就需要你自己管理合同了。这时一般要注意这几个事项。
第一,金融合同签订以后,买卖双方需要履行合同义务,也就是按照合同声明的金额进行资金往来,因此需要有**支付系统**和**会计系统**。
第二,资金转账通常不能在节假日进行,所以需要**日期系统**来通知系统自动调整日期。
第三,你需要随时知道自己的资产有多少,风险有多大,这里需要有**风险计算系统**。
那么,一个简单的衍生品管理系统就成型了,它需要下面这些不同的领域系统:
<img src="https://static001.geekbang.org/resource/image/47/10/47f7f7932b1fef0f169517cb5aa47a10.jpg" alt="">
到这里,我们完成了衍生品管理系统的初步设计。接下来我们来做个练习,看看如何将每个部分划分到正确的领域。
我们先来看看哪几个是核心领域。你做资产管理是为了获得合理的收益,所以核心业务应该和金融产品的收益相关。这里我们发现有两个系统组件比较相关,分别是定价和风险计算系统,所以这两个属于核心领域。
至于打印、支付、会计、日期变更等都是常见功能。除了金融行业,很多其他行业也有,所以这些都是通用功能,属于通用领域。
但是相对而言,交易、报价和生命周期管理没那么通用,但是也不属于核心竞争力,因此这些都属于支持型领域。下面这幅图展示了我们划分下来的结果:
<img src="https://static001.geekbang.org/resource/image/b5/4f/b5fc9274efed338a1fafb8ba1077614f.jpg" alt="">
## 小结
这节课我们介绍如何通过领域驱动设计来对金融系统做顶层设计。设计的两个核心原则是**追求投资回报比,以及长期优化。**
领域驱动设计首先解决了人的问题。软件系统研发是多个部门通力合作的结果。合作的过程需要有效的沟通,因此建议直接沟通,而不是采用传统的层级式沟通方式。沟通时不同部门的人需要尽量了解对方的术语。当大家有了共同的术语后还要沉淀下来,形成领域语言。
理顺了人之后,我们就可以解决事情了。领域驱动设计将复杂的系统组件分为三大领域。核心领域与金融公司的核心竞争力有直接关系。通用领域可以跨不同行业。支持型领域负责支持核心领域,跨行业的可能性较低。
最后我们结合前面所学的内容,通过分析衍生品管理这个业务,练习了如何分析必须的系统组件,以及如何划分这些组件的领域。
<img src="https://static001.geekbang.org/resource/image/09/c0/092212acf6da83a6e1f651a2557278c0.jpg" alt="">
## 思考题
两个不同领域之间传输的数据类型也是有讲究的。一般来说有两种选项:
1. 传输的是领域模型。
1. 传输的是简单数据类型比如POJOPlain Old Java ObjectJson等。
如果你是一家大金融公司的CTO需要进行公司级别的领域驱动设计。这时除了需要考虑软件本身的设计外还需要结合公司的人员变更现状10%的平均年员工流动率和公司未来10年的软件发展计划金融业务变更非常频繁
现在你需要拿出一份指导意见,那么你会选择传输哪种数据类型呢?
欢迎留言和我分享你的想法。如果这节课让你有所收获,也欢迎分享给你的朋友,一起交流进步。

View File

@@ -0,0 +1,224 @@
<audio id="audio" title="05 | 领域驱动设计(下):如何设计统一的金融业务模型?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/9c/5b/9c6bf0e2fbbe580c85fc5b0174db145b.mp3"></audio>
你好,我是任杰。这节课我想和你聊一聊怎么设计统一的金融模型。
[上节课](https://time.geekbang.org/column/article/325378)我带你了解了,如何通过领域驱动设计的方法来设计金融软件的顶层架构。我们知道了金融软件的核心原则之后,今天我们来学习实际的金融架构设计和建模,看看金融行业的一些通用的软件设计和分析方法。
这节课会涉及到一些英文专有名词。我用表格形式做了梳理,你可以在进入正文之前先了解一下:
<img src="https://static001.geekbang.org/resource/image/eb/42/ebdf4a7b0820c529ee11ecd516145142.jpg" alt="">
## 金融业务背景假设
在上节课我们说过领域驱动设计的过程非常耗时耗力,所以从性价比角度考虑的话,尽量只用这个方法来解决复杂金融业务的问题。
那么这节课,我要先选择一个既容易让你理解,又足够复杂的金融业务例子。
也许你还记得,我们在[第3节课](https://time.geekbang.org/column/article/324871)里给你说到了很多金融业务。其中交易类业务和场内交易业务都相对简单。所以我们如果想要找复杂的例子就需要定位在场外交易的产品类型。场外交易最简单的类型就是期权Option所以我们可以选择**债券期权**Bond Option这个金融业务的例子。
正式分析系统架构之前,我们先来看看需要解决的金融业务细节。
债券期权本身也是一个期权Option。你购买了期权之后就有了一个**选择的权利**。在期权到期日那天,你可以选择用期权规定的价格来购买债券。
如果这时候期权价格比市场价低,你可以用低的期权价格来购买债券,同时以更高的价格卖出去,这样一买一卖就能马上获利。但是如果期权价格比市场价格高,你可以选择什么都不做,就当没有买过这个期权一样。
当然了,你也可以选择买了债券之后不卖出去。这时候你就拥有了这个债券。债券的发行人会定期给你利息,比如半年一次或者一年一次。
你可能已经发现了,期权给你的选择权力可以让你永赚不赔。金融行业都是聪明人,这么好的事情显然不可能是免费的。你需要花钱来买债券期权,所以债券期权本身是有价格的。
由于不知道未来债券价格会怎么波动,所以我们只能根据自己对各种未来概率的假设来估算债券期权的价格。这个估算的过程就是**债券期权的定价过程**。如果你认为的债券期权的真正价格比券商卖的要高,就可以从券商那里买入这个债券期权。
定价过程有两个最重要的输入,一个是债券的**所有未来现金流**,另一个是债券**价格的历史数据**。还有一些比较重要的数据,比如**无风险利率**和债券发行方的**信用数据**等,我们都归类于**市场数据**。
你如果在金融行业有一定经验就会发现这里对业务做了很大的简化。比如我们举例的债券期权其实是叫看涨期权Call Option类似的还有看跌期权Put Option。只能在到期日行权的期权类型叫作欧式期权European Option类似的还有美式期权American Option
这些简化是为了方便你理解,并不会影响后面架构分析的正确性。你如果对金融业务有兴趣,可以自行研究各种不同的场外金融业务。
例子选完了,接下来我们从建模逻辑和生命周期两个方面进行分析。
## 建模逻辑
### 实体Entity
在进行领域驱动设计建模的时候,首先要确认的是有哪些是**实体**。
**实体是具有唯一标识符的业务对象**。你可以**用唯一标识符来区分不同的业务对象。**如果你见过债券的话,会发现它和人民币很像,都是在角落里印上一串数字。这个就是债券的唯一标识符。
债券期权虽然是一个纯电子合同但是它也有唯一标识。对开发人员来说唯一标识符就是一串字符串比如UUID。债券期权这个实体的示意图如下图中“待补充”的内容后面我们会逐渐补全
<img src="https://static001.geekbang.org/resource/image/5d/b2/5de67befb71c5e15029ae0c3b47b08b2.jpg" alt="">
债券和债券期权这两个实体有一个共同点,它们都不会凭空产生和消失。它们都有一个日期叫作**发行日期**,这就是它们出现的一天。它们也有**到期日期**。
金融合同在发行日期和到期日期之间,还会规定一些其他的资金行为。我们把金融合同从产生到消失的整个过程叫作**生命周期**。另外,这个金融合同我们会通过唯一标识符进行管理。
说到这里我们总结一下,实体有这样三个特点:
1.有唯一标识符。<br>
2.用唯一标识符来判断是否是同一个实体。<br>
3.有生命周期管理。
反过来说,如果一个金融业务对象具有上面这三个特点,那么它很有可能被建模成实体。在这个债券期权的例子里,期权和债券都是实体。
期权对应了一个未来**可能的资金流**Optional Cashflow这个资金流会不会发生取决于你是否行权。这个可能的资金流也是实体。债券的**资金流**Cashflow相对来说比较确定也是实体。债券现金流是由债券**利息**Interest构成的这个利息也是实体。
我们把所有的实体和它们之间的引用关系画出来就是下面这张图:
<img src="https://static001.geekbang.org/resource/image/81/bc/816012yy829de24bc0bae3dbd3af4abc.jpg" alt="">
### 值对象Value Object
和实体对应的另一个概念是值对象Value Object
顾名思义值对象里的“对象”就是面向对象编程OOP里的对象Object“值”表示这个对象里只有值没有其他东西。这么定义你可能感觉比较抽象我们来看一个具体的值对象例子。
金融合同一定会规定合同涉及到的金额Notional。金额就是一个值对象。金额本身由币种Currency和数额Amount两个信息组成。
如果一个金额是100元人民币而另一个金额也是100元人民币我们会说这两个金额相等。
因为我们在判断金额是否相等的时候并没有用到任何唯一标识符,这说明了值对象并不是由唯一标识符决定的,而是由它内部的组成内容决定的。所以当我们判断两个值对象是否相等时,只能比较值对象内容。
前面讲的债券期权例子中也有几个值对象。前面提到的金额是一种。还有期权行权的日期和行权方式。我们再仔细分析的话,会发现行权日期里的日期也属于值对象。我们把值对象加上之后的示意图如下:
<img src="https://static001.geekbang.org/resource/image/d5/15/d5d7b17d968546ece92c68498df6f815.jpg" alt="">
另外还有一些和债券期权没有直接关系的**市场数据也是值对象**,比如无风险市场利率。市场利率的示意图如下:
<img src="https://static001.geekbang.org/resource/image/65/c2/653eb3f167d524217a7754e92599c0c2.jpg" alt="">
和实体相比,值对象还有一个不一样的地方,就是**应该怎么正确修改值对象**。比如说债券利息原来的金额是100元人民币。现在想修改成200元人民币。那我们应该怎么实现呢
我们在修改值对象之前要先找到值对象。你不能像对待实体一样,通过唯一标识符找到值对象。那应该如何访问它呢?
这就要说到值对象的另一个特点。值对象一定是作为实体的附属品存在的,**值对象其实是实体的一个属性。<strong>你只能**通过建模对象之间的引用关系顺藤摸瓜地找到值对象。**我们通常会说一个对象具有**状态</strong>State**值对象是用来表示这些状态的。**
找到值对象之后,接下来我们就可以来解决怎么修改值对象了。因为值对象没有唯一标识符,你一旦修改了值对象里的内容,这个值对象本身就会变得不一样,所以**修改值对象的过程其实是替换值对象的过程。**
领域驱动设计里,值对象的修改方法更极端。既然值对象的修改就是替换,那还不如**将所有值对象的所有属性都设置成只读。**这样既能满足值对象修改的要求,又能避免无意之中的修改。
这里我给你梳理一下,值对象有这些特点:
1.没有唯一标识符。<br>
2.有内部属性。<br>
3.通过比较内部属性来判断是否相等。<br>
4.不可修改。修改会返回新的值对象。<br>
5.不能独立存在,是其他实体或者值对象的附属品。
要重点提醒你的是,**业务对象属于实体还是值对象并不是一成不变的**。比如我们在数钱的时候,每张人民币纸钞都是一样的,人民币的纸钞可以作为值对象存在。但是如果我们想判定人民币真伪的时候,就需要检查人民币的编号,这时候会用到人民币的唯一标识符,人民币纸钞也就变成了实体。
所以这和上一节课核心领域和通用领域的区分标准一样,一个业务对象是属于实体还是值对象要取决于具体的问题,需要我们合理判断。
### 领域服务Domain Service
**领域服务其实就是这个领域相关的服务**。我们今天提到一个词叫**业务逻辑**。如果业务逻辑跨了多个实体,或者任何一个实体都不适合包含所有业务逻辑,那么用来承载业务逻辑的主体就是领域服务。
通俗来说,领域服务就是我们常说的业务逻辑,负责处理各种业务实体,也顺便通过实体来处理各种值对象。
金融行业的领域服务有一些独有的特性。首先,领域服务不附属于任何一个实体或者值对象。它自身独立存在。
其次,金融产品的领域服务有一个设计原则是**无状态**。无状态指的是它内部没有维护全局状态,整个计算过程也不能有任何随机性。请注意这是金融行业的设计原则,而不是所有行业都有这个要求。因为金融行业对正确性要求非常高,做任何计算都建议不要出现不确定性。这也是为什么金融系统架构普遍都是**不可变架构**Immutable Architecture
总结一下,领域服务有这些特点:
1. 代表业务逻辑,处理实体和值对象。
1. 本身无状态。
1. 不依附于任何实体或者值对象。
在债券期权的例子中,买卖合同时的**定价**Pricing过程是一个领域服务合同的**风险计算**Risk Calculation也属于领域服务。我们把领域服务补全之后的示意图如下
<img src="https://static001.geekbang.org/resource/image/d7/d6/d7613fc2840eceb3545b558431746ed6.png" alt="">
## 生命周期管理
### 聚合Aggregate
**单个聚合**
我们在前面说过实体是有生命周期的,我们需要对生命周期进行管理。
但是通常生命周期管理不是以单个实体为粒度进行管理的。你应该能从上面那些示意图里感受到实体之间存在着非常复杂的引用关系,彼此之间形成了一个引用关系图。如果你对引用关系图中的任何一个实体节点进行操作,势必会影响到周边的实体节点。
如果你不考虑这些被影响的周边实体节点,那么整个系统的状态会变得不一致。一个办法是对影响的范围做一个划分。这个划分就是**聚合**。从图论的角度来看,聚合就是一个有向图的子图。
聚合规定了一个影响范围的边界。它有一个**唯一入口**叫作聚合根Aggregation Root。聚合根一定是一个实体通过它可以访问到所有跟它相关的其他实体或者值对象。
比如开头例子的债券期权Bond Option它就是一个聚合根。通过它可以访问到债券起源合同的其他内容。债券期权的聚合和聚合根示意图如下
<img src="https://static001.geekbang.org/resource/image/43/f2/430cd5f71082e3c6d8c912b558a0f1f2.png" alt="">
聚合除了定义影响力边界以外,还同时定义了**存储边界**。**聚合里面所有内容需要在一个数据库事务内操作**。
聚合的存取管理由我们这节课最后提到的**仓库**Repository来负责。读取的时候是先通过聚合根的唯一标识符来获取聚合根然后再通过聚合根将聚合里剩下的内容从数据库拉出来。仓库在进行数据存取的时候需要合理选择数据解决方案我会在[第10节课](https://time.geekbang.org/column/article/332304)里给你详细分析。
我们前面只提到了聚合的边界但是没有说边界究竟有多大。其实大和小没有统一标准需要具体情况具体分析。一般来说你要注意这3点
1.聚合里节点的关系尽量形成有向无环图。
2.聚合的关系图尽量小一点。这样数据库事务小,存取速度快。
3.聚合的关系图如果太大的话,需要做一些优化。一般采用**延时访问**Lazy Loading的方法。当你访问聚合根的时候系统并没有将所有内容从数据库加载进来等访问到具体内容的时候才会加载。这样就能摊销数据加载时间也可以节省不必要的数据库访问。
**多个聚合**
前面提到过,聚合是引用关系图的一个子图。当你把所有聚合划分好之后,会发现聚合之间也是存在引用关系的。比如一个聚合内部的实体节点可能需要访问另一个聚合内的节点。那多个聚合之间的访问应该遵守什么规则呢?
我们学习单个聚合时提过,只能通过聚合根来访问聚合内的元素。这个规定依然需要遵守。但是我们没有规定谁可以访问聚合根,所以一个聚合的内部节点也能访问另一个聚合的聚合根,甚至可以将聚合根的唯一标识符作为值对象存储下来。
我们还是拿债券期权这个金融产品举例,债券是期权的底层资产,因此期权这个实体需要能访问债券这个实体。体现在架构图上,就是在债券期权这个聚合内部,有节点可以访问债券这个聚合根。示意图如下:
<img src="https://static001.geekbang.org/resource/image/14/76/1429a2ac3f596a62b6cc1f397d57e876.png" alt="">
讲完了多个聚合的访问原则,我们再来看看多个聚合怎么处理存储。前面说过,单个聚合的存储需要在一个数据库事务内处理,这样多个事务的存储就会跨不同事务,情况会更加复杂。
我们可以选择用一个更大的事务来包含所有单个聚合的事务。但这样会导致事务范围过大,存储内容的范围不确定,存储的效率偏低。所以在实践中一般会放弃用数据库事务来存储多个聚合。
这时候的**存储原则是最终一致性**只要最终所有聚合都能被正确存储就行不需要在存储的中间过程中满足数据库事务的ACID要求。因为最终一致性会导致系统在存储的中途出现不一致的状态所以在做架构设计时我们要提前考虑这些情况应该如何处理具体怎么处理我在后面[第13节](https://time.geekbang.org/column/article/335994)和[14节课](https://time.geekbang.org/column/article/336686)会讲到。
聚合的内容到这里就讲完了。下图展示了完整的聚合划分结果:<br>
<img src="https://static001.geekbang.org/resource/image/9a/55/9af83f5fc822fc2c7f3ef133ebdb0c55.png" alt="">
### 工厂Factory
领域驱动设计将业务对象的创建与使用分开。**业务对象的使用由领域服务来负责,而创建由工厂来负责**。
因为领域驱动设计里的工厂Factory和设计模式里的工厂作用完全一样你可以查看设计模式相关内容比如《设计模式可复用面向对象软件的基础》或者《深入浅出设计模式》。
### 仓库Repository
仓库负责所有业务对象的存储。领域驱动设计对存储也有一些独到的建议,我们下面就来看看。
仓库和现在基于服务的架构SOAService Oriented Architecture里的数据访问层DALData Access Layer层很像主要解决内存数据的序列化问题。但是从领域驱动设计的角度来看仓库其实起到的是一个**防腐化层**Anti-corruption Layer的作用。
防腐化层也是领域驱动设计里的一个术语,它解决了两个系统在协议变更之后如何进行交互的问题。一般防腐化层会介于新老两个系统中间,它负责将老系统和老协议包装成一个使用新协议的系统,这样新的系统无论怎么变化,老系统都会安然无事。
所以防腐化指的是不让外部协议的变化来入侵内部协议。由于变化入侵通常会让系统架构变得更差,入侵的过程就是腐化的过程。
仓库也能防腐化,它分隔了数据的使用和存储,这样数据使用的变化就不会影响到数据存储。如下图所示,左边是防腐化层的示意图,右边是仓库的示意图:
<img src="https://static001.geekbang.org/resource/image/29/f0/29e3485e1e35e119271eb53e92b244f0.jpg" alt="">
由于仓库负责业务对象的存储,我们自然会想到用仓库来做数据分析。不过,我**不建议你使用仓库来做数据分析。领域驱动设计里有专门的事件溯源和CQRS来解决数据分析问题**。我会在后面几节课给你详细讲解。
## 小结
这节课我给你讲了怎么设计统一的金融模型,具体要从建模逻辑和生命周期两个方面来看。
建模逻辑分为三个大的方向:实体、值对象和领域服务。
实体是有唯一标识的业务实体,有生命周期,有状态,有业务逻辑。相对而言,值对象没有唯一标识符,是通过自己内部属性来判断是否和其他人一样。它没有生命周期,通常是作为实体的属性或者状态存在。领域服务只包含业务逻辑,不包含任何状态。它通过操作实体和值对象来实现最终的功能。
而生命周期管理也分为三个大的方向:聚合、工厂和仓库。
聚合将紧密相关的实体和值对象组合成一个原子单元。外界只能直接访问这个原子单元的根结点,不能直接访问内部节点。这个原子单元的存取需要通过数据库事务来保证数据的完整性和一致性。工厂负责生成聚合。仓库负责将聚合序列化和反序列化。
领域驱动设计的建模过程会指导你深入思考金融业务涉及的对象和它们的逻辑,这样有利于划分系统组件边界和区分组件的重要性。而领域驱动设计对生命周期管理的一些思考,能帮助你从时间维度思考合理的金融对象管理方式。
**所以有了领域驱动设计的指导,你设计出来的系统不仅仅现在是合理的,在将来也可能是合理的,这样就<strong><strong>能**</strong>增加金融系统演进的正确性。正确性是金融系统最重要的要求。</strong>
<img src="https://static001.geekbang.org/resource/image/98/2b/98ce8f0158e480daeee5d6800a132b2b.jpg" alt="">
## 思考题
债券期权有一个行权日。实际经常会出现金融公司忘记了行权的情况。假设你需要实现一个自动通知的功能,如果债券期权没有行权,相关用户需要在第一时间收到相关通知。那你会怎么实现这个功能呢?是作为实体的内部逻辑,还是领域服务,或者是我们这节课还没有提到的其他数据分析方法?
欢迎留言和我分享你的想法。如果这节课让你有所收获,也欢迎你分享给朋友、同事,一起交流进步。

View File

@@ -0,0 +1,118 @@
<audio id="audio" title="答疑集锦(一) | 思考题解析与外汇架构知识拓展" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/67/0d/67410668dd5290d1b9bb97463611970d.mp3"></audio>
你好,我是任杰。
在2021年的第一天祝你元旦快乐。一元复始万象更新希望你在新的一年里工作顺利学习进步。
到今天为止我们学完了第一个模块金融业务与系统的内容。我专门为你准备了这篇加餐把前5节课的思考题做了一个系统梳理。我建议你先仔细学习前面每一讲的内容自己独立思考之后再来看我这份参考答案。
## 思考题答案
[**第1节课**](https://time.geekbang.org/column/article/323701)
Q第三方支付公司在做外汇交易的时候不会只碰到单一方向的汇兑业务。既然有人民币到美元的转换那么也会碰到美元到人民币的转换。汇兑提供商的收费只和交易数量有关和交易币种无关。如果你是负责第三方支付公司的资金管理你有什么方法能进一步降低汇兑成本吗
A按照从简单到复杂的顺序外汇业务的发展可以分成两步。第一步是先**尽快支持业务**。公司在联系好外汇提供商后,将客户的每笔外汇交易都交给中间商处理,自己赚一点手续费。这一步的重点是收集用户的交易行为,为之后的外汇自营作准备。
当第一步成熟之后,公司再进行第二步,做**财务优化**。优化的主要方向是减少跟中间商的交易次数方法是建立外汇资金池。公司在资金池内放一部分自有资金作为垫资Floating。对于每个不同币种都需要有资金池这样就能把外汇交易分解为单币种交易。
建立好资金池之后,外汇交易就和平时的单币种交易一样了。公司可以利用自己的清结算能力来对业务进行轧差。
唯一会出现问题的是当单向交易过多时,资金池的资金会不够用。这时候第一步的预测能力就能帮上忙,公司财务部门要能提前预测流动性不足的风险,提前做好外汇购买来补充资金池的资金。如果来不及的话,还可以复用第一步的行为,将所有的外汇交易代理给交易商处理。
[**第2节课**](https://time.geekbang.org/column/article/324117)
Q假设支持外汇业务的第三方支付公司自己拥有大量的人民币和美元储备可以在外汇支付过程中充当买家和买家共同的对手方即买家的人民币支付给电商公司随即电商公司将自己拥有的美元支付给卖家。那么为了支持外汇业务支付公司的架构应该做如何调整呢
A一笔外汇其实是两笔同币种的交易所以在处理的时候你可以当作没有外汇这件事情。这里我们需要生成两笔不同币种的支付订单然后想办法分别将这两个支付订单关联起来就行了。关联的目的主要是把当时的外汇和手续费等信息记录下来这样日后才能方便对账。
在实际实现的时候,一般都会把外汇单独拿出来做一个外汇系统。这个系统会提供外汇的基本功能,比如外汇的购买、与汇兑提供行对接,以及外汇资产管理系统。你可以把外汇资产管理系统当成另一种点券系统,只不过这时候的点券是不同国家的货币。
这时候系统的交互也会稍微发生一些变化。业务系统需要先向外汇系统查询合适的外汇报价,然后生成外汇支付订单。
[**第3节课**](https://time.geekbang.org/column/article/324871)
Q在上世纪中期的美国银行的定义是吸纳存款并且发放贷款。一旦一家金融机构被定性成为了银行就需要接受美联储监管。监管会限制金融机构的行为因此金融机构并不一定愿意成为银行。那么如果你是一家银行的 CEO既不想被美联储定性成银行又想做一些银行的事情你准备做怎样的业务调整呢
A我们来看一下数理逻辑。这里的“并且”是个并列关系所以只要有一个条件不满足金融机构就不是银行了。
一种选择是只吸纳存款,不发放贷款。这样没有多大意义,因为存款是有利息的,银行会一直往外出钱。
另一种选择是只发放贷款,不吸纳存款。这个选择看起来好像可行,因为至少银行可以通过放贷来赚利息。但是不吸纳存款的话,银行的自有资金总会枯竭的。
那该怎么办呢?这时候的解决办法是将用户的存款换一种形式。用户将钱交给银行后并不是拿回存折,而是会转成公司股份。这样银行就能合法地规避对银行的规定了。显然这种做法是钻了监管漏洞,所以很快也被堵住了。
[**第4节课**](https://time.geekbang.org/column/article/325378)
Q两个不同领域之间传输的数据类型也是有讲究的。一般来说有两种选项
1. 传输的是领域模型
1. 传输的是简单数据类型比如POJOPlain Old Java ObjectJson等
假设你是一家金融公司的CTO需要进行公司级别的领域驱动设计。这时候需要考虑的除了软件本身的设计外还需要结合公司的人员变更现状10%的平均年员工流动率和公司未来10年的软件发展计划金融业务变更非常频繁。现在你需要给出一份指导意见那么你会选择传输哪种数据类型呢
A这道题我认为要分情况讨论小公司和大公司的考虑点会有所不同。
小公司的开发人员少,因此有可能做到大家互相都很了解对方的信息,加上小公司普遍要求上线速度快,所以一般会选择实现快的方式,放弃长期的可维护性。因此在小公司里,选择用简单数据类型的会比较多,不同系统之间通过数据库交流。这也是互联网公司在创业期的普遍思路。
而大公司的开发人员相对较多因此需要先假设他们不能完全了解对方。这时候部门或组件之间的低效沟通是效率低下的一个主要原因。那选择用POJO的话效率就没有之前那么高了。
POJO的问题在于它是二进制表现形式缺乏了对象Object的行为。在缺乏的行为中最重要的就是逻辑校验的能力。所以POJO的使用方需要重构所有的业务验证逻辑这相当于从二进制数据中反编译出原来的业务行为。
我们知道,大公司会有很多不同类型的业务数据,这就会导致很容易出现反编译的错误。
如果从POJO切换到有领域内容的对象模型也会有问题。这时候公司会面临一个过渡期。简单的数据类型和带业务逻辑的领域模型会在一段时间内同时存在这时候公司需要同时维护两种不同的数据会在短时间内加重系统的维护成本。
这时候就是考验公司领导层的时候了。我们在讲投资回报比的时候讲的是长期回报。领导层需要根据公司对未来的计划来合理选择究竟应该走哪条路。
对于金融公司来说,对正确性要求非常高,因此会选择在初期就使用领域模型。当然了,随着互联网行业对金融行业的渗透,互联网的一些做法也带入到了金融行业,这些做法也取得了一些不俗的效果。究竟是劣币驱逐良币,还是模式上的创新,我们拭目以待。
[**第5节课**](https://time.geekbang.org/column/article/327137)
Q债券期权有一个行权日。一个经常出现问题是金融公司忘记了行权。假设你需要实现一个自动通知的功能如果债券期权没有行权相关用户需要在第一时间收到相关通知。那么你会怎么实现这个功能呢是作为Entity的内部逻辑还是Domain Service或者是作为我们这一节还没有介绍到的数据分析
A行权自动通知由于涉及到多个实体所以是一个领域服务。它的操作对象是实体的行权日期也就是值对象。它在通知用户的时候需要使用到消息系统这是一个通用领域。
好了,第一模块的思考题答案解析就说到这里。我还想给你补充一下外汇系统的架构知识,如果你学有余力,可以作为拓展阅读学习,如果跳过这段内容,也不会影响你对整个专栏的把握。
## 外汇系统
这里我们着重看一下和第三方支付相关的外汇系统。做跨境电商的机构很可能需要对接具有外汇支付能力的第三方支付公司。
还是老规矩我们在讲系统架构前先看一下业务。外汇支付和外汇交易都需要外汇系统也都有购换汇过程。但是涉及到的主体和钱不同。在外汇交易的过程中两个主体互相交换不同币种的货币其金额比率由汇率决定。外汇支付涉及4个主体。
我们还是拿电商举例一位中国用户用70元人民币购买10美元物品。中国用户先将这70元转给第三方支付公司的人民币账户。第三方支付公司再从自己的美元账户内转10美金给卖家。第三方支付公司不能凭空转出美元。它需要通过外汇交易的方式获得美元。
具体过程是第三方支付公司从外汇交易商那里提前用70元人民币购买10美元并将美元存放至美元资金池内。示意图如下
<img src="https://static001.geekbang.org/resource/image/17/56/174429b31a1f836fec75e026da785856.jpg" alt="">
那我们来看一下系统架构。由于外汇系统是利用自有资金池做交易,属于内部资产管理,需要内部资产管理系统。因此外汇系统和第三方支付公司的资金池处理非常类似,多数组件也能复用。
对于外汇系统来说,其购换汇过程要通过外部资产管理系统来完成。金融网关此时对接的是外汇交易商,而不是第三方支付公司。
如下图所示,外汇系统多出来的一个组件是汇率查询系统。这个系统负责提供当前可交易汇率给跨境电商的支付页面。
<img src="https://static001.geekbang.org/resource/image/50/3a/50e7byy9004d595c8f994b23956a433a.jpg" alt="">
在外汇系统中有一个不可或缺的组件是清算中心。用到清算中心主要是为了节省外汇交易成本。
我还是拿跨境电商举例。中国买家可以买美国产品,美国买家也可以买中国产品。这两个相反的过程对于支付公司来说可以彼此对冲,从而能减少资金流的交易笔数,进而节省交易成本。请你注意,这里需要清算中心来做相应的优化。
当然了,为了方便你理解,上面的架构示意图是简化版本。在实现过程中有很多可以优化的地方。和数学的合并同类项一样,外汇系统和支付系统有很多可以合并的组件,比如账务系统、金融网关、资产管理系统、核算系统等等。你需要根据实际情况来灵活选择。
其实外汇交易是一个很大的命题,比如有时候第三方支付公司会将外汇支付代理给另一家具有外汇支付能力的第三方支付公司,这时候架构需要对应调整。
在实际购换汇过程中司库Treasury部门需要根据未来几天的外汇支付行为来计算需要购换汇的金额所以外汇系统还需要具有一定机器学习的能力。有兴趣的同学还可以自行查阅相关专业领域的内容。
## 思考题的出题思路
最后,我还想和你聊一聊,我是怎么设置思考题的?
金融业务的发展具有规模优势。如果一家金融公司规模越大,涉及到的领域越多,那么它就越能给用户提供更全面的服务,利润也越高。
所以,金融公司的发展有一个特点,那就是公司会不断追逐高利润点的新业务。对于金融系统来说,我们开发人员面对的挑战是不断会有新的业务需求。
罗马不是一天建成的,金融系统也不是一次就能搭好的。我们不可能在搭建系统的时候就能完美解决未来所有的金融问题,因此我们还要学会如何不断升级现有的系统。这就是我们思考题的出发点,希望能带你思考业务会有哪些发展,系统应该有哪些对应的改进。
以上就是今天的全部内容了,希望能够对你有所帮助。下节课,我们将要进入到第二个模块了,预祝你学习愉快,希望我们后面有更多的交流,一同学习进步。