从零开始学学架构-完结
2019-11-29 14:58:33 1 举报
AI智能生成
从零开始学架构
作者其他创作
大纲/内容
01 | 定义
软件架构指软件系统的顶层结构
架构是顶层设计;框架是面向编程或配置的半成品;组件是从技术维度上的复用;模块是从业务维度上职责的划分;系统是相互协同可运行的实体。
02 | 历史背景
随着软件系统规模的增加,计算相关的算法和数据结构不再构成主要的设计问题;当系统由许多部分组成时,整个系统的组织,也就是所说的“软件架构”,导致了一系列新的设计问题
03 | 架构设计的目的
是为了解决软件系统复杂度带来的问题
04 | 复杂度来源:高性能
单机复杂度
操作系统的复杂度直接决定了软件系统的复杂度
操作系统和性能最相关的就是进程和线程
多进程多线程虽然让多任务并行处理的性能大大提升,但本质上还是分时系统,并不能做到时间上真正的并行
目前这样的解决方案有 3 种:SMP(Symmetric MultiProcessor,对称多处理器结构)、NUMA(Non-Uniform Memory Access,非一致存储访问结构)、MPP(Massive Parallel Processing,海量并行处理结构)
集群的复杂度
任务分配
分支主题
任务分解
业务简单的时候 1 台机器扩展到 10 台机器,性能能够提升 8 倍(需要扣除机器群带来的部分性能损耗,因此无法达到理论上的 10 倍那么高),但如果业务越来越复杂,1台机器扩展到 10 台,性能可能只能提升 5 倍。造成这种现象的主要原因是业务越来越复杂,单台机器处理的性能会越来越低。为了能够继续提升性能,我们需要采取第二种方式:任务分解。
好处
可以针对单个任务进行扩展
简单的系统更加容易做到高性能
评论区
05 | 复杂度来源:高可用
定义
系统无中断地执行其功能的能力,代表系统的可用性程度,是进行系统设计时的准则之一。高性能增加机器目的在于“扩展”处理性能;高可用增加机器目的在于“冗余”处理单元
作用
数据+逻辑=业务,数据不正确就会导致业务错误(银行存钱栗子)
存储高可用的难点不在于如何备份数据,而在于如何减少或者规避数据不一致对业务造成的影响
CAP 定理
存储高可用不可能同时满足“一致性、可用性、分区容错性”,最多满足其中两个,这就要求我们在做架构设计时结合业务进行取舍。
高可用状态决策
1. 独裁式
独裁式决策指的是存在一个独立的决策主体,我们姑且称它为“决策者”,负责收集信息然后进行决策;所有冗余的个体,我们姑且称它为“上报者”,都将状态信息发送给决策者。
2. 协商式
协商式决策指的是两个独立的个体通过交流信息,然后根据规则进行决策,最常用的协商式决策就是主备决策
协商式决策的架构不复杂,规则也不复杂,其难点在于,如果两者的信息交换出现问题(比如主备连接中断),此时状态决策应该怎么做
3. 民主式
指的是多个独立的个体通过投票的方式来进行状态决策
民主式决策比协商式决策要复杂得多,ZooKeeper 的选举算法 Paxos
06 | 复杂度来源:可扩展性
指系统为了应对将来需求变化而提供的一种扩展能力,当有新的需求出现时,系统不需要或者仅需要少量修改就可以支持,无须整个系统重构或者重建。
基本条件
正确预测变化
预测变化的复杂性在于
不能每个设计点都考虑可扩展性。
不能完全不考虑可扩展性。
所有的预测都存在出错的可能性
完美封装变化
将“变化”封装在一个“变化层”,将不变的部分封装在一个独立的“稳定层”。
方法
(1)从业务维度。对业务深入理解,对可预计的业务变化进行预测。
(2)从技术维度。利用扩展性好的技术,实现对变化的封装。
(1)使用分布式服务(框架)构建可复用的业务平台
利用分布式服务框架(如Dubbo)可以将业务逻辑实现和可复用组件服务分离开,通过接口降低子系统或模块间的耦合性。新增功能时,可以通过调用可复用的组件实现自身的业务逻辑,而对现有系统没有任何影响。可复用组件升级变更的时候,可以提供多版本服务对应用实现透明升级,对现有应用不会造成影响。
(2)使用分布式消息队列降低业务模块间的耦合性
基于生产者-消费者编程模式,利用分布式消息队列(如RabbitMQ)将用户请求、业务请求作为消息发布者将事件构造成消息发布到消息队列,消息的订阅者作为消费者从消息队列中获取消息进行处理。通过这种方式将消息生产和消息处理分离开来,可以透明地增加新的消息生产者任务或者新的消息消费者任务。
07 | 复杂度来源:低成本、安全、规模
低成本
当我们设计“高性能”“高可用”的架构时,通用的手段都是增加更多服务器来满足“高性能”和“高可用”的要求;而低成本正好与此相反,我们需要减少服务器的数量才能达成低成本的目标。因此,低成本本质上是与高性能和高可用冲突的,所以低成本很多时候不会是架构设计的首要目标,而是架构设计的附加约束。也就是说,我们首先设定一个成本目标,当我们根据高性能、高可用的要求设计出方案时,评估一下方案是否能满足成本目标,如果不行,就需要重新设计架构;如果无论如何都无法设计出满足成本要求的方案,那就只能找老板调整成本目标了。
低成本给架构设计带来的主要复杂度体现在,往往只有“创新”才能达到低成本目标
安全
安全本身是一个庞大而又复杂的技术领域,并且一旦出问题,对业务和企业形象影响非常大
1. 功能安全
常见的 XSS 攻击、CSRF 攻击、SQL 注入、Windows 漏洞、密码破解等
功能安全其实就是“防小偷”
2. 架构安全
架构安全就是“防强盗”
规模
规模带来复杂度的主要原因就是“量变引起质变”
1. 功能越来越多,导致系统复杂度指数级上升
2. 数据越来越多,系统复杂度发生质变
分而治之,各个击破”的方法策略
08 | 架构设计三原则
合适原则
合适优于业界领先
为什么
没那么多人,却想干那么多活,是失败的第一个主要原因
没有那么多积累,却想一步登天,是失败的第二个主要原因
没有那么卓越的业务场景,却幻想灵光一闪成为天才,是失败的第三个主要原因
简单原则
简单优于复杂
复杂度体现
1. 结构的复杂性
组成复杂系统的组件数量更多
同时这些组件之间的关系也更加复杂
2. 逻辑的复杂性
单个组件承担了太多的功能
演化原则
演化优于一步到位
首先,设计出来的架构要满足当时的业务需要
其次,架构要不断地在实际应用过程中迭代,保留优秀的设计,修复有缺陷的设计,改正错误的设计,去掉无用的设计,使得架构逐渐完善
第三,当业务发生变化时,架构要扩展、重构,甚至重写;代码也许会重写,但有价值的经验、教训、逻辑、设计等(类似生物体内的基因)却可以在新架构中延续
09 | 架构设计原则案例
通过文中对淘宝和手机 QQ 两个典型互联网业务的架构发展历程的详细拆解,可以看出,大型互联网架构发展的最重要甚至唯一的驱动力就是\"情非得已\",伴随业务的高速发展,用户、数据、流量、业务复杂度都在呈指数级增长,总会突破现有商业、开源条件能够提供的解决方案的有效范围,企业发展到一定程度最终还是要立足自力更生,去摸索、去创新适合自己需求、符合自己业务体系的系统架构。
在淘宝和qq的前面两个阶段都是采用了合适和简单原则,在第三个阶段候才采用的演化原则。前面的阶段技术实现要快,要快速的满足业务发展的需要,技术以够用为主。后面的技术选型就以发展为主,要为后来的发展奠定基础。这也给公司在大的技术路线选择上提供了参考
有些公司要求两三年就重构一次
互联网时代机会稍纵即逝,所以要快速出一个基础产品,要快,要活下来先!然后随着业务的发展,逐步演进架构,当然这里面也涉及到一些技术架构的决策。
10 | 架构设计流程:识别复杂度
构建复杂度的来源清单——高性能、可用性、扩展性、安全、低成本、规模等
将主要的复杂度问题列出来,然后根据业务、技术、团队等综合情况进行排序,优先解决当前面临的最主要的复杂度问题
11 | 架构设计流程:设计备选方案
备选方案的数量以 3 ~ 5 个为最佳
备选方案的差异要比较明显
备选方案的技术不要只局限于已经熟悉的技术。架构师需要将视野放宽,考虑 更多可能性
备选阶段关注的是技术选型,而不是技术细节,技术选型的差异要比较明显
12 | 架构设计流程:评估和选择备选方案
如何挑选出最终的方案也是一个很大的挑战,主要原因有
每个方案都是可行的,如果方案不可行就根本不应该作为备选方案
没有哪个方案是完美的。例如,A 方案有性能的缺点,B 方案有成本的缺点,C 方案有新技术不成熟的风险
评价标准主观性比较强,比如设计师说 A 方案比 B 方案复杂,但另外一个设计师可能会认为差不多,因为比较难将“复杂”一词进行量化。因此,方案评审的时候我们经常会遇到几个设计师针对某个方案或者某个技术点争论得面红耳赤
很多设计师思想
最简派
挑选一个看起来最简单的方案
最牛派
倾向于挑选技术上看起来最牛的方案
最熟派
基于自己的过往经验,挑选自己最熟悉的方案
领导派
让领导来定夺,反正最后方案选的对那是领导厉害
正确做法
“360 度环评”!具体的操作方式为:列出我们需要关注的质量属性点,然后分别从这些质量属性的维度去评估每个方案,再综合挑选适合当时情况的最优方案。
常见的方案质量属性点有:性能、可用性、硬件成本、项目投入、复杂度、安全性、可扩展性等。在评估这些质量属性时,需要遵循架构设计原则 1“合适原则”和原则 2“简单原则”,避免贪大求全,基本上某个质量属性能够满足一定时期内业务发展就可以了
13 | 架构设计流程:详细方案设计
详细设计方案阶段可能遇到的一种极端情况就是在详细设计阶段发现备选方案不可行,一般情况下主要的原因是备选方案设计时遗漏了某个关键技术点或者关键的质量属性
架构师不但要进行备选方案设计和选型,还需要对备选方案的关键细节有较深入的理解
通过分步骤、分阶段、分系统等方式,尽量降低方案复杂度
14 | 高性能数据库集群:读写分离
将数据库读写操作分散到不同的节点上
15 | 高性能数据库集群:分库分表
场景
子主题 1
业务分库
按照业务模块将数据分散到不同的数据库服务器
表单数据拆分
垂直分表
业务对数据的操作主要集中在某些字段上
水平分表
业务对数据的操作在整个表层面较均匀分布
16 | 高性能NoSQL
K-V存储:解决关系数据路无法存贮数据结构的问题,以Redis为代表
文档数据库:解决关系数据库强schema约束问题,以MongoDB为代表
列试数据库:解决关系数库大数据场景下的I/O问题,以HBase为代表
全文搜索引擎:解决关系数据库的全文搜索性能问题,以Elasticsearch为代表
17 | 高性能缓存架构
缓存就是将可能重复使用的数据放到内存中,一次生成,多次使用,避免每次使用都去访问存储系统
要点
缓存穿透
缓存没哟发挥作用,缓存中没有数据
存储数据不存在了
缓存数据生成耗费大量时间或资源
缓存雪崩
缓存失效后引起系统性能急剧下降
更新锁机制
对缓存更新进行枷锁保护,保证只有一个线程能够进行缓存更新
后台更新机制
由后台线程来更新缓存,而不是由业务线程来更新缓存,缓存本身的有效期设置为永久,后台线程定时更新缓存
缓存热点
对于一些特别热点的数据,大部分业务都要请求,缓存热点解决方案就是复制多份缓存副本,将请求分散到多个缓存服务器上,减轻缓存热点导致的单台缓存服务器压力
18 | 单服务期高性能模式:PPC与TPC
关键就是:服务器采取并发模型
I/O模型:阻塞、非阻塞、同步、异步
进程模型:单进程、多进程、多线程
PPC
每次有新的连接就新建一个进程去专门处理这个连接请求
TPC
共享进程内存空间
19 | 单服务期高性能模式:Reactor与Proactor
20 | 高性能负载均衡:分类及架构
高性能集群的复杂性主要体现在需要增加一个任务分配器(负载均衡器),以及为任务选择一个合适的任务分配算法
分类
DNS负载均衡
就近访问
硬件负载均衡
通过硬件设备实现负载均衡
软件负载均衡
通过软件实现负载均衡
Ngin\\LVS
21 | 高性能负载均衡:算法
负载均衡算法
轮询
按照顺序轮流分配到服务器上,无须关注服务器本身的状态
加权轮询
根据服务器权重进行任务分配,这里的权重一般是根据硬件配置进行静态配置的,其目的就是为了解决不同服务器处理能力有差异的问题
负载最低优先
将任务分配给当前负载最低的服务器(问题是当前负载最低不好判断)
性能最优类
将任务分配给处理速度最快的服务器,通过这种方式达到最快响应客户端目的
22 | CAP理论
对于一个分布式计算系统,不可能同时满足一致性(Consistence)、可用性(Availability)、分区容错性(Partition Tolerance)三个设计约束
一致性
对某个指定的客户端来说,读操作保证能够返回最新的写操作结果
可用性
非故障的节点在合理的时间内返回合理的响应
分区容忍性
当出现网路分区后,系统能够继续“履行职责”
23| 想成为架构师,你必须掌握的CAP细节
子主题 2
CAP是忽略网络延迟的
ACID是数据库管理系统为了保证事务的正确性而提出来
Atomicity(原子性)
一个事务中的所有操作,要么全部完成,要么全部不完成,不会再中间某个环节结束。发生错误会回滚
Consistency(一致性)
在事物开始之前和事物结束以后,数据库的完整性没有被破坏
Isolation(隔离性)
数据库允许多个并发事物同时对数据进行读写改,隔离性可以防止多个事物并发执行
Durability(持久性)
事物处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失
BASE核心思想是及时无法强一致,但应用可以采取合适的方式达到最终一致性
基本可用(Basically Available)
分布式在出现故障时,语序损失部分可用性,即保证核心可用
软状态(Sost State)
允许系统存在中间状态,而该状态不会影响系统整体可用性
最终一致性(Eventual Consistency)
系统中的所有数据副本经过一定时间后,最终能够达到一致的状态
评论
24 | FMEA方法,排除架构可用性隐患的利器
(Failure mode and effects analysis,故障模式与影响分析)
给出初始的结构设计图
假设结构中某个部件发生故障
分析此故障对系统功能造成的影响
根据分析结果,判断结构是否需要进行优化
图表法
25 | 高可用存储架构:双机架构
26 | 高可用存储架构:集群和分区
27 | 如何设计计算高可用架构?
28 | 业务高可用的保障:异地多活架构
29 | 异地多活设计4大技巧
30 | 异地多活设计4步走
31 | 如何应对接口级的故障
32 | 可扩展架构的基本思想和模式
基本思想一个字:拆,将原本大一统的系统拆分成多个小规模的部分,扩展时只修改其中一部分即可,无须整个系统到处修改
拆分思路
面向流程拆
将整个业务流程拆分为几个阶段,每个阶段作为一部分
面向服务拆
将系统提供的服务拆分,每个服务作为一部分
面向功能拆
将系统提供的功能拆分,每个功能作为一部分
架构图
33 | 传统的可拓展架构模式:分层架构和SOA
分层架构
C/S架构、B/S架构(浏览器/服务器)
MVC架构、MVP架构
划分的对象是单个业务子系统,划分的维度是职责,将不同的职责划分到独立层,但各层的依赖关系比较灵活
逻辑分层架构
划分的对象是单个业务子系统,也可以是整个业务系统,划分的维度是职责。虽然都是基于职责划分,但逻辑分层架构和MVC\\MVP不同点在于,逻辑分层架构中的层是自顶向下依赖的
分层架构的核心点:需要保证各层之间的差异足够清晰,边界足够明显,让人看到架构图后就能看懂整个架构
34 | 深入理解微服务架构:银弹 or 焦油坑
35 | 微服务架构最佳实践:方法篇
36 | 微服务架构最佳实践:基础设施篇
37 | 微内核架构详解
38 | 架构师应该如何判断技术演进的方向?
潮流派
对新技术特别热衷,紧跟技术潮流
自己可能就是小白鼠;新技术学习花费时间
保守派
对新技术包邮很强戒备心,稳定压倒一切,已经掌握某种技术,就一直用这种技术打天下
不能享受新技术带来的收益
跟风派
技术演进动力就是业务
影响一个企业发展三要素:市场、技术、管理。业务是处于三角形中心,这三者都是为了支撑业务发展
技术演进模式
基于业务发展阶段判断
39 | 互联网技术演进的模式
40 | 互联网架构模板:“存储层”技术
41 | 互联网架构模板:“开发层”和“服务层”技术
42 | 互联网架构模板:“网络层”技术
43 | 互联网架构模板:“用户层”和“业务层”技术
44 | 互联网架构模板:“平台层”技术
45 | 架构重构内功心法第一式:有的放矢
重构中往往会有很多问题,在这么多问题中识别出重构的目标,并不是一目了然。而如果想一下子全部解决所有问题人力不够!所以架构师需要透过问题表象看到问题本质,找出真正需要通过架构重构解决的核心问题,从而做到有的放矢。
46 | 架构重构内功心法第二式:合纵连横
合纵
让需求、开发、测试等人员目标达成一致,用易于理解的沟通方式去进行
连横
对于大型重构可能会进行好几个组或部门进行,始终要以整个项目为中心,不能有私心。换位思考、合作共赢、关注长期
47 | 架构重构内功心法第三式:运筹帷幄
如何在100个问题中,找出重构点
优先级排序
问题归类
先易后难
循序渐进
48 | 再谈开源项目:如何选择、使用以及二次开发?
49 | 谈谈App架构演进
50 | 架构实践:架构设计文档模板
备选方案模板
需求介绍
主要描述需求的背景、目标、范围等
需求分析
主要全方位的描述需求相关的信息
5W
8C
复杂度分析
高可用
高性能
可扩展
备选方案
至少3个,最多5个
架构设计模板
总体方案
从整体上描述方案的结构,其核心内容就是架构图,以及针对架构图的描述,包括模板或者子系统的职责描述、核心流程
架构总览
给出架构图以及架构描述
核心流程
详细设计
高可用设计
高性能设计
可扩展设计
安全设计
身份识别权限等
其他设计
开发语言、公司标准等
部署方案
硬件要求、服务器部署方式、组网方式
架构演进规划
通常情况下,规划和设计的需求比较完善,但如果一次性全部做完,项目周周期可能比较长,因此可以采取分阶段实施,即:第一期做什么、第二期做什么,以此类推
架构师成长之路-第四期
内功心法
判断力
能够准确的判断系统的复杂度在哪
执行力
能够使用合适的方案解决复杂度问题
创新力
能够创造新的解决方案解决复杂度问题
成长之路:工程师--》高级工程师--》技术专家--》初级架构师--》中级架构师--》高级架构师
架构师专栏-第二期
设计原则
架构约束
甲方要求必须运用某种技术
不要做PPT架构师
广度
深度
架构师专栏-第一期
提升技术的重要手段:写博客
10000小时理论
吃的草够多,你也能成为大牛
书籍
技术
《UNIX编程艺术》
个人成长
《异类》
人生境遇
《羊皮卷》
结束语-坚持,成就你的梦想
坚持学习
学基础知识、学理论知识、学业界新的技术、研究开源系统、研究业界实践,既要有技术广度,又要有技术深度
坚持输出
培训、演讲、写博客、写书
如何高效的学习开源项目
不要“拿来主义”,要“知其然,知其所以然”
每一个开源项目中都会有收获
不要只盯着数据结构和算法
采取“自顶向下”学习方法
源码不是第一步,而是最后一步。不要一上来就去看源码,而是要基本掌握了功能、原理、关键设计之后再去看源码,看源码的主要目的是为了学习其源码的写作方式,以及关键技术实现
架构考虑核心
功能需求、非功能需求
功能需求
开发人员必须在产品中实现的软件功能,用户利用这些功能来完成任务,满足业务需求
非功能需求
指依一些条件判断系统运作情形或其特性,而不是针对系统特定行为的需求
安全性、可靠性、互操作性、健壮性、易使用性、可维护性、可移植性、可重用性、可扩充性
性能/容量
性能和容量比较利于理解,包括像需要支持的用户的数量啊(尤其是峰值的并发用户数量),用户能够接受的响应时间啊,数据规模啊(例如@子柳 提到的百万级的惊人数据规模,上亿的文件存储啦等等。这里小小纠正一下@子柳 的一个观点,百万级的数据支撑,还是有一些商业数据库产品可以支持的,TPC-C/TPC-D以及新一代的业界性能测试标准中还有千万级数据规模的测试项目,也有数据库厂商报名参加的,当然,对于淘宝这样的业务模式和实际情况/要求来说,性价比和实用性可能确实就比较低了)
可靠性/可用性/可复原性
可靠性之与在规定的一段时间和条件下软件维持其功能服务以及性能水平的能力有关的一组属性(可用性是另外一种说法)。例如说我们要求系统7x24小时运行,全年持续运行故障停运时间累计不能超过10小时等等,都属于这方面的要求。 可复原性与在是发生错误和故障后重建其性能水平并恢复直接受影响数据的能力。例如支付宝需要保证如果在交易提交失败以后,需要保证回滚,不能这头银行的钱没有付成功,那头却显示付款成功或者反之这头银行扣款了,那头在改变交易状态的时候缺因为冗塞或者其他原因导致交易还是未付款状态。
可维护性/可管理性
包括系统在无人工干预条件下的稳定性,自排错能力,可测试性都属于这个范畴。故障的可排查能力,系统的修正,升级,备份,恢复机制以及方便与否,都属于这个范畴。这通常会极大决定系统的运行维护成本及维护难度。
包括传输加密,存储加密,可破解性,以及各种未被授权的用户行为如何防范和控制,都是安全范畴,这里的安全不单针对外部普通用户,也针对内部不同级别的权限用户的的控制。小到如何防范和处理用户在输入框里输入特殊字符来获得设计者未曾预料的结果,大到防范外部黑客和内部内鬼。安全很多时候不单依赖技术实现,同时非常依赖相应的制度和审计。
易用性
易用性设计现在已经上升到了一个新的高度,叫做人机体验,UE设计,虽然现在UE到底是划分在功能性需求还是非功能性需求上,尚有一些争议,但是主流观点(包括我自己)都认为,这是非功能性需求的一个典型部分。
数据一致性
包括数据的编码和语言,冗余数据的一致性要求(含时间要求)等等。例如为了性能的考虑,数据库整体设计未采用巴斯克范式,而采用了第二或者第三范式的要求来设计,一些信息(例如用户注册信息),可能同时存在于系统的多个地方(例如多个表中),当发生注册信息变更时,如何保证多处地方记录的信息都被修改,以及这个全部修改的时限要求是多少等等都是这个范畴的内容。
系统/环境 条件及限制
现有的软硬件条件,平台的条件,网络的条件都属于这个范畴。典型的例如很多移动互联网产品,必须要考虑移动网络的带宽条件,终端运算性能和能力,以及其移动网络稳定性等等。
5种架构视图
逻辑架构
逻辑架构关注的是功能,包含用户直接可见的功能,还有系统中隐含的功能。或者更加通俗来描述,逻辑架构更偏向我们日常所理解的“分层”,把一个项目分为“表示层、业务逻辑层、数据访问层”这样经典的“三层架构”。
开发架构
开发架构则更关注程序包,不仅仅是我们自己写的程序,还包括应用程序依赖的SDK、第三方类库、中间价等。尤其是像目前主流的Java、.NET等依靠虚拟机的语言和平台,以及主流的基于数据库的应用,都会比较关注。和逻辑架构有紧密的关联。
运行架构
更关注的是应用程序运行中可能出现的一些问题。例如并发带来的问题,比较常见的“线程同步”问题、死锁问题、对象创建和销毁(生命周期管理)问题等等。开发架构,更关注的是飞机起飞之前的一些准备工作,在静止状态下就能规划好做好的,而运行架构,更多考虑的是飞机起飞之后可能发生的一些问题。
物理架构
更关注的系统、网络、服务器等基础设施。例如:如何通过服务器部署和配置网络环境,来实现应用程序的“可伸缩性、高可用性”。或者举一个实际的例子,如何通过设计基础设施的架构,来保障网站能支持同时10W人在线、7*24小时提供服务,当超过10W人或者低于10W人在线时,可以很方便的调整部署架构来支撑。
数据架构
更关注的是数据持久化和存储层面的问题,也可能会包括数据的分布、复制、同步等问题。更贴切来讲,如何选择需要的关系型数据库、流行的NOSQL,如何保障数据存储层面的性能、高可用性、灾备等等。很多时候,和物理架构是有紧密联系的,但它更关注数据存储层面的,物理架构更关注整个基础设施部署层面。
图解
从零开始学架构
收藏
0 条评论
下一页