用了1天时间编的一个架构演进的故事, 帮助学生理解架构及其演进过程. 欢迎批评指正和转载.
业务架构的演进
以银行为例展现架构的演变. [用了1天时间编一个架构演进的故事]
-
最早期是一个人 A 0 A_0 A0负责全部存贷款活动. 相当于单机程序.
-
随着业务的增加, 发现忙不过来了. 于是雇佣 B 0 B_0 B0负责记账. A 0 A_0 A0负责接待客户和处理业务逻辑, B 0 B_0 B0相当于数据库服务器.
- 还有一个方案是加盟连锁, 雇佣
A
1
A_1
A1和
A
0
A_0
A0自己做同样的业务. 但是客户的账户在
A
0
A_0
A0和
A
1
A_1
A1之间同步需要时间和精力.
- 随着业务的增加, 于是雇佣人数越来越多. A 1 , A 2 , . . . , A n A_1, A_2, ..., A_n A1,A2,...,An做和 A 0 A_0 A0同样的负责接待客户和业务逻辑. n n n可以任意大.
- 账户同步的消耗越来越大. 完全同步是
2
n
−
1
2^{n-1}
2n−1, 通信量增长过快, 时间消耗过长.
- 逐渐出现专门负责账户同步的 M M M. 形成P2P架构, 其关键是能够查询账户由哪个 A i A_i Ai负责.
- 一个办法是不同步账户数据. 由每个
A
i
A_i
Ai负责不同的客户, 采用专属客户经理制度.
- 每个客户由其专属的客户经理 A i A_i Ai负责. 业务数据和业务处理局部化.
- 客户之间的操作, 例如转账, 可能在需要多个客户经理参与. 形成分布式事务.
- 还有是提升每个客户经理可以负责的客户数量, 进行业务活动过程分工, 与下面的情况相同.
- 还有一个方案是加盟连锁, 雇佣
A
1
A_1
A1和
A
0
A_0
A0自己做同样的业务. 但是客户的账户在
A
0
A_0
A0和
A
1
A_1
A1之间同步需要时间和精力.
-
随着业务的继续增加, 可能发现 A 0 A_0 A0自己又忙不过来了. 于是雇佣了 A 1 , A 2 , . . . , A n A_1, A_2, ..., A_n A1,A2,...,An做和 A 0 A_0 A0同样的负责接待客户和业务逻辑. n n n可以任意大.
- B 0 B_0 B0的工作量越来越大. 假设暂时还挺得住, 后面讨论记账的扩容问题.
-
随着业务的继续增加, A 0 A_0 A0觉得可以继续分工. 于是雇佣 C 0 C_0 C0负责处理业务逻辑. A 0 A_0 A0和 A 1 , A 2 . . . , A n A_1,A_2...,A_n A1,A2...,An负责接待客户.
-
随着业务的继续增加, C 0 C_0 C0忙不过来了. 于是雇佣 C 1 , C 2 , . . . , C m C_1, C_2, ..., C_m C1,C2,...,Cm做和 C 0 C_0 C0同样的负责处理业务逻辑. m m m可以任意大.
- 客户来个由任意一个 A i A_i Ai接待, 交流好业务后, 到任意一个 C j C_j Cj处理业务逻辑, 到 B 0 B_0 B0记账.
-
随着业务的继续增加, 终于 B 0 B_0 B0忙不过来了. 于是雇佣 B 1 , B 2 , . . . , B p B_1, B_2, ..., B_p B1,B2,...,Bp和 B 0 B_0 B0同样负责记账.
- 账户在 B 0 . . . B p B_0...B_p B0...Bp之间同步, 需要话费时间和精力. - 分布式系统的延时造成数据一致性困难.
- 多个客户对同一个客户的支付业务, 需要保持操作结果的正确性. - 需要操作的原子性, 数据一致性.
- 其中 B 0 . . . B o B_0...B_o B0...Bo负责记账, B o + 1 . . . B p B_{o+1}...B_p Bo+1...Bp负责查询余额开存款证明等查账服务. - 读写分离
-
随着业务的增加, 账户同步的消耗越来越大. 于是考虑减少同步的需要.
- 把客户的账户分区, 每个
B
k
∈
{
B
0
,
.
.
.
,
B
p
}
B_k \in \{B_0,..., B_p\}
Bk∈{B0,...,Bp}只负责一部分账户. 每个账户只有特定的一个
B
k
B_k
Bk负责. - 数据分区
- 同步还是有的, 例如账户之间的转账. 可能两个账户在不同分区, 分布式事务出现了. 但毕竟一个 B k B_k Bk内的账户之间不用分布式事务.
- 按照不同的业务把账户不同方面的信息, 由不同的
B
k
B_k
Bk负责. 例如, 账户口令表, 账户余额表, 存款记录表, 取款记录, 贷款记录表等分给不同不同的
B
k
B_k
Bk负责. - 数据库分表分库.
- C j C_j Cj处理一个业务时, 可能需要到几个不同的 B k B_k Bk. 增加了处理业务逻辑工作量.
- 为了减少 C j C_j Cj的难度, 把业务逻辑按照账户的不同方面分开, 由不同的 C j C_j Cj负责. C j C_j Cj需要处理的业务逻辑就简单一些了, 招人和培训变得容易, 功能也相对稳定.
- 通过组合这些 C j C_j Cj就可能提供新业务, 例如, 组合出存款送鸡蛋活动, 贷款送大米等活动, 可以在原有的存款/贷款的基础上增加送鸡蛋, 送大米活动即可. 再招一批专门负责设计组织这些业务活动的 D 0 . . . D q D_0...D_q D0...Dq. 称为市场经理.
- 把客户的账户分区, 每个
B
k
∈
{
B
0
,
.
.
.
,
B
p
}
B_k \in \{B_0,..., B_p\}
Bk∈{B0,...,Bp}只负责一部分账户. 每个账户只有特定的一个
B
k
B_k
Bk负责. - 数据分区
总结一下:
-
A
0
.
.
.
A
n
A_0...A_n
A0...An负责客户交流, 然后领着客户到
D
0
.
.
.
D
q
D_0...D_q
D0...Dq参加活动.
- 活动的数量可能小于 q q q. 可以根据不同的客户分配给不同的市场经理.
-
D
0
.
.
.
D
q
D_0...D_q
D0...Dq以
C
0
.
.
.
C
m
C_0...C_m
C0...Cm的基本业务为基础模块, 设计业务活动流程.
- 基本业务的数量可能小于 m m m. 可以根据不同的用户分配给不同的业务基础模块副本.
- C 0 . . . C m C_0...C_m C0...Cm处理特定的业务逻辑, 并要求对应的 B 0 . . . B p B_0...B_p B0...Bp负责记账.
- 可能业务基础模块与记账模块(数据库)一一对应. 也可能几个模块公用一个数据库. 也可能一个基础业务模块需要使用多个数据库
这样的架构在可以业务分工, 用户分区两个维度进行业务容量的扩展. 当然也可以在雇员能力(单机性能)上左垂直扩展. 这些 D 0 . . . D q D_0...D_q D0...Dq和 C 0 . . . C m C_0...C_m C0...Cm称为微服务.
软件架构模式的演进
从单机程序, 到C/S架构, B/S架构, 多层B/S架构, 多层架构, 微服务架构的演化过程如下.
应用场景 | 架构 | 效果 |
---|---|---|
功能简单, 数据量小 | 单机架构 | 简单, 容易掌握 |
多用户 | C/S架构 | 多用户并发执行业务 |
客户端程序部署速度慢, 升级工作量大, 用户数量大 | B/S架构 | 用户有浏览器就可以工作 |
业务逻辑复杂 | 多层B/S架构 | 业务逻辑规范, 开发分工明确 |
多种客户端, 特别是移动客户端 | 多层架构 | 移动端和网页端功能一致 |
业务功能多, 业务流程变化大, 新业务上线时间短 | 微服务架构 | 开发新业务速度快, 版本更新快 |