一、架构设计基础
系统:
- 能力/职责
- 关联
- 规则
模块 VS 组件:
- 逻辑视角拆分后的单元,划分模块的主要目的是职责/功能分离。
- 物理视角拆分后的单元,划分组件的主要目的是单元复用。
框架 VS 架构:
- 框架关注的是规范
- 架构关注的是结构
架构: 软件架构指软件系统的顶层结构
架构设计的主要目的: 为了解决复杂度带来的问题
软件复杂度的来源:
- 高性能
- 高可用
- 可扩展
- 低成本
- 安全
- 规模
二、架构设计原则
架构设计原则:
- 合适原则:合适优于业界领先
- 简单原则:简单优于复杂
- 演进原则:演化优于一步到位
软件领域的复杂性:
- 结构复杂性
- 逻辑复杂性
演化原则:
原则总结:
三、架构设计流程
识别复杂度 >> 设计备选方案 >> 评估和选择备选方案 >> 详细方案设计
四、存储高性能
4.1 关系数据库
关系数据库:
- 读写分离
- 分库分表
分库分表实现上更加复杂
读写分离:
主从架构,一主一从,或一主多从
分库:
业务分库
分表:
- 水平分表
- 垂直分表
读写分离、分库分表本质上:
都是一种分配机制,将不同的 SQL 语句发送到不同的数据库服务器
实现方式:
- 程序代码封装
- 中间件封装
中间件封装/数据库中间件:
数据库中间件服务器,对业务服务提供 SQL 兼容的协议,对于业务服务来说,访问中间件和访问数据库没有区别
4.2 NoSQL
关系数据库的不足:
对应 NoSQL 解决方案:
K-V 存储缺点:
value 是一个数据结构。无法保证原子性和持久性。
文档数据库:
列式数据库优势:
列式数据库不足及应用场景:
全文搜索引擎:
4.3 缓存
基本原理:
将重复使用的数据放在内存中,一次生成,多次使用(如读多写少的场景) ,避免每次使用都去访问存储系统。
缓存穿透: 缓存没有发挥作用。
缓存雪崩: 缓存失效(过期)后,重新生成缓存时,系统性能急剧下降
缓存热点: 通过多个缓存服务器分散单一缓存服务器的压力
五、计算高性能
计算高性能:
- 单服务器高性能
- 集群高性能
集群高性能:
- DNS 负载均衡
- 硬件负载均衡
- 软件负载均衡
DNS 负载均衡: 实现地理级别的均衡
优点:
- 简单,成本低
- 就近访问,提升访问速度
缺点:
- 更新不及时
- 扩展性差
- 分配策略简单
- 无法感知后端服务器状态
HTTP-DNS: 私有的 DNS 系统
优缺点正好与 DNS 默认优缺点相反
硬件负载均衡:
通过单独的硬件设备来实现负载均衡功能,如 F5,A10
软件负载均衡:
通过负载均衡软件来实现负载均衡功能。如 Nginx 和 LVS
硬件与软件负载均衡对比:
软件负载均衡优缺点:
负载均衡架构:
实际当中,可以将多种负载均衡方式组合起来使用
负载均衡算法:
- 任务平分类
- 负载均衡类
- 性能最优类
- Hash 类
六、CAP
对于一个分布式系统,不可能同时满足一致性、可用性和分区容错性。
在分布式系统中,当涉及到读写操作时,只能保证一致性、可能性和分区容错性三者中的两个,另外一个必须被牺牲。
一致性:
对某个指定的客户端来说,读操作保证能够返回最新的写操作结果。
可用性:
非故障的结点在合理的时间内返回合理的响应。
分区容错性:
当出现网络分区后,系统能够继续履行职责。
分区:
网络节点之间通信出现了问题,可能是丢包,也可能是连接中断,还可能是拥塞。整个网络就分成了几块区域。数据就散布在了这些不连通的区域中。这就叫分区。
CAP 中,现实中,P 是一定存在的。
七、FMEA
一种可用性分析方法,通过对系统范围内潜在故障模式加以分析,并按照严重程度进行分类,以确定失效对系统的最终影响,并评估可能需要采取的规避措施。
八、存储高可用
存储高可用本质:
通过将数据复制到多个存储设备,通过数据冗余的方式来实现存储高可用。 复杂性:
如何应对复制延迟和中断导致的数据不一致问题
思考和分析要点:
- 数据如何复制
- 各个节点的职责是什么
- 如何应对复制延迟
- 如何应对复制中断
常见高可用存储架构:
- 主备复制
- 主从复制
- 主主复制
- 数据集群
- 数据分区
8.1 主备复制
存储系统一般都提供了主备复制的功能。如 MySQL、Redis、MongoDB。
8.2 主从复制
主机负责读写操作,从机只负责读操作,不负责写操作。
写少读多的业务场景,使用主从复制存储架构比较多。例如论坛、BBS、新闻网站等。
8.3 主主复制
两台机器都是主机,互相将数据复制给对方,客户端可以任意挑选其中一台机器进行数据读写操作。
8.4 数据集群
数据集中集群
数据分散集群
8.5 数据分区
数据分区,区指的是地区。
数据分区主要应对地理级别的故障。
九、计算高可用
计算高可用架构的复杂度主要体现在任务管理方面,即任务在哪台服务器上执行,以及当任务执行失败后,如何将任务重新分配到新的服务器执行。
9.1 主备架构
9.2 主从架构
9.3 对称集群
9.4 非对称集群
十、业务高可用
- 异地多活
- 降级
- 熔断
- 限流
- 排队
降级: 核心思想是丢车保帅,优先保证核心业务
熔断: 当依赖的外部系统故障导致系统自身不可用时,进行熔断
限流: 只允许系统能够承受的用户量进来访问,超出系统访问能力的用户将被抛弃
排队: 是让用户等待很长时间
十一、可扩展模式
可扩展架构设计背后一个基本思想是:拆
拆分软件系统方式有三种:面向流程拆分、面向服务拆分和面向功能拆分。
十二、分层架构
分层架构的类型:
- C/S 架构、B/S 架构:划分的维度是用户交互,即将和用户交互的部分独立为一层,支撑用户交互的后台作为另外一层。
- MVC 架构、MVP 架构:划分维度是职责,将不同的职责划分到独立的层。
- 逻辑分层架构:最常见的分层架构,划分维度是职责,各层是由上往下依赖的。
要点:
- 分层架构需要保证各层之间差异尽量清晰,边界足够明显。
- 分层架构之所以能够较好支撑系统扩展,本质在于:隔离关注点。
十三、SOA 架构
SOA 架构:面向服务的架构
一种架构设计理念,异构系统之间,通过向其他系统提供服务的方式,解决系统间的连通。
十四、微服务
SOA 与微服务对比:
微服务问题:
十五、微内核架构
微内核架构,也称之为插件化架构。
包含两类组件:
- 核心系统
- 插件模块
核心系统: 负责与具体业务功能无关的通用功能,例如模块加载、模块间通信等。
插件模块: 负责实现具体的业务逻辑。
关键设计点:
- 插件管理: 管理插件,如有哪些插件可用,如何加载,加载时机等
- 插件连接: 插件如何连接到核心系统
- 插件通信: 插件间的通信
插件化架构示例:Eclipse 的 OSGI,电商系统的规则引擎等。
十六、消息队列设计实战
- 识别复杂度
- 更多关注 1s 的数据,如 TPS、QPS
- 性能、技术、业务需求特点、运维团队经验、已有技术体系、团队人员的技术水平都会影响到方案选择。
十七、互联网架构演进
- 互联网业务千差万别,但都具有“规模决定一切”的特点
- 互联网业务发展,第一个主要方向是“业务越来越复杂”
- 互联网业务发展,第二个主要方向是“用户量越来越大”
- 互联网业务发展,带来复杂度本质原因,都是“量变带来质变”
十八、互联网架构模板
- 框架的选择,有一个总的原则:优选成熟的框架,避免盲目追逐新技术
- 配置中心主要是为了解决系统数量增多后,配置管理复杂和效率低下问题
- 服务中心目的,是解决跨系统依赖的配置,和调度问题
- 消息队列的目的,是为了实现跨系统异步通知
- DNS 是最简单也是最常见的负载均衡方式,一般用来实现地理级别的均衡
- F5、A10,用来实现集群级别负载均衡
- Nginx、LVS 用来实现机器级别负载均衡
- CDN 为了解决用户网络访问“最后一公里”效应,本质上是一种以空间换时间的加速策略
- 多机房设计最核心的设计因素是如何处理时延带来的影响
- 业务层降低复杂度最好的方式是“拆”,化整为零,分而治之。将整体复杂性分散到多个子业务或子系统中去
- 运维平台核心职责:配置、部署、监控、应急
- 测试平台核心目的是提升测试效率,从而提升产品质量,其设计关键是自动化
- 数据平台核心职责:数据管理、数据分析和数据应用
- 管理平台核心职责是权限管理
十九、架构重构
- 架构重构涉及关联方配合时,有效的沟通策略是“换位思考、合作共赢、关注长期”
- 架构重构需要采取“分段实施”,将要解决的问题根据优先级、重要性、实施难度划分为不同的阶段,每个阶段聚焦于一个整体的目标
二十、开源系统
- 是否选择开源系统,最终取决于成本收益比,聚焦于是否能满足业务需要
- 选择开源项目时,尽量选择成熟的开源项目
- 选择开源项目时,除了关注技术指标,还要关注运维能力
- 不能简单“拿来主义”,还要深入研究和仔细测试
- 使用时,对线上风险要有敬畏之心,小心应用,灰度发布
- 考虑应急的备份方案