架构学习-复杂度来源
架构设计的主要目的是为了解决软件系统复杂度带来的问题,那么复杂度的来源到底在哪里呢?
1. 高性能
1.1 单机复杂度
操作系统 - 是将硬件性能充分发挥出来的关键。
- 最初是只有输入计算以及输出功能
- 批处理 - 将要执行的指令预先写下来,形成一个指令清单,然后将任务交给计算机执行,读取任务中的指令清单并进行处理
- 进程 - 进程对应任务,都有自己的内存空间,进程间互不相关
- 进程间的通信
- 管道
- 消息队列
- 信号量
- 共享存储
- 线程
- 进程内部的子任务,都共享同一份进程数据。为保证数据的正确性,有了互斥锁机制。有了多线程以后,操作系统调度的最小单位就变成了线程,而进程变成了操作系统分配资源的最小单位。
- 多个CPU真正同时执行计算任务
- SMP symmetric multi processor
- NUMA Non uniform memory access
- MPP Massive Parallel Processing
1.2 集群复杂度
突然发现双十一峰值,支付宝能到每秒12万笔;红包能达到76万。通过大量机器来提升性能,并不仅仅是增加机器这么简单,让多台机器来配合达到高性能的目的,是一个复杂的任务,复杂在于:
- 任务分配
- 任务分配器
- 硬件网络设备 交换机
- 软件网络设备 LVS
- 负载均衡软件 Nginix HAProxy
- 分配算法
- 轮询
- 按权重分配
- 按负载分配
- 任务分配器和业务服务器的连接
- 选择合适的连接方式
- 管理连接
- 连接建立,检测,中断后的处理
- 继续拓展 -> 任务分配器也要变成多台了
- 此时需要将不同的用户分配到不同的任务分配器上
- DNS轮询,CDN, GSLB(Global Server Load Balance)
- 任务分配器和业务服务器,多对多的网状结构
- 此时需要将不同的用户分配到不同的任务分配器上
- 任务分配器
- 任务分解
- 任务分配到不同的机器上带来的帮助会递减的,因为当业务越来越复杂,单台机器的性能不够用了,所以就需要进行任务分解来做优化
- 可以从逻辑上将各个子业务进行拆分,将一整个业务系统拆分成小而简单,但是需要多个系统配合的业务系统
- 为什么能提升性能? 代码还是那些代码哇?
- 简单的系统更容易分析出瓶颈,更容易做到高性能
- 可以针对单个任务进行拓展
- 当然不能划分的太细,因为网络的调用性能远比系统内的函数调用要低
2. 高可用
系统无中断地执行其功能的能力,代表系统的可用性程度
通过冗余来实现高可用,与高性能的区别在于,高性能增加机器的目的在于扩展处理性能;高可用增加机器的目的在于冗余处理单元
2.1 计算高可用
多台服务器时主备的选择,具体采用什么方式,主备分别的个数,结合实际业务需求来分析和判断。
2.2 存储高可用
高可用设计的关键点就在于存储高可用了,区别在于将数据从一台机器搬到另一台机器,需要经过线路进行传输
无论是正常情况下的传输延迟,还是异常情况下的传输中断,都会导致系统的数据在某个时间点或者时间段是不一致的,而数据的不一致又会导致业务问题;存储高可用的难点不在于如何备份数据,而在于如何减少或者规避数据不一致对业务造成的影响。
分布式领域的CAP定理,存储高可用性不可能同时满足一致性,可用性,分区容错性,最多满足其中两个,这就要求我们在做架构设计的时候结合业务进行取舍。
2.3 高可用状态决策
无论是计算高可用还是存储高可用,其基础都是状态决策,即系统需要能够判断当前的状态是正常还是异常的,如果出现异常就要采取行动来保证高可用。但一个矛盾点在于:
通过冗余实现的高可用,状态决策本质上就不可能做到完全正确
常见的决策方式:
- 独裁式
- 只有一个决策者
- n个上报者
- 不会出现决策混乱,但是决策者本身故障的时候,系统就崩了
- 协商式
- 两个独立的个体通过交流信息,根据规则进行决策
- 主备决策
- 2台服务器启动时都是备机
- 建立连接
- 交换状态信息
- 某1台服务器做出决策,成为主机;另一台继续保持备机身份
- 协商式 当连接出问题的时候,采用哪个? 两主? 多连接? 仍然存在问题的
- 民主式
- 多个独立个体通过投票的方式进行状态决策
- ZooKeeper集群在选举leader时就采用这种方式
- 对于连接断开,可能出现多个leader的问题的解决
- 投票节点数必须超过系统总结点数的一半的规则
3. 可拓展性
- 可拓展性指系统为了应对将来的需求变化而提供的一种扩展能力,当有新的需求出现的时候,系统不需要或者仅仅需要少量修改就可以支持,无须整个系统的重构或者重建。
- 面向对象的思想以及设计模式的诞生与演化,都是在努力提升代码的可拓展性
- 设计具备良好可拓展性的系统的基本条件
- 正确预测变化
- 不能每个点都考虑可拓展性
- 不能完全不考虑可拓展性
- 所有的预测都存在出错的可能性
- 完美封装变化
- 一般来说会将变化封装在一个变化层,将不变的部分封装在一个独立的稳定层
- 或者提炼出一个抽象层和一个实现层
- 正确预测变化
4. 低成本,安全,规模
- 低成本
- 通过减少服务器的数量来达成低成本的目标
- 首先指定一个成本目标,当我们根据高性能、高可用的要求设计出方案时,评估一下方案能否满足成本目标,如果不行,就要重新设计架构
- 通过引入新技术来达到目标
- NoSQL 解决关系型数据库无法应对高并发情况下的访问压力的问题
- 全文搜索引擎是为了解决关系型数据库like搜索的低效的问题
- Hadoop的出现是为了解决传统文件体统无法应对海量数据存储和计算的问题
- 安全
- 功能安全
- XSS攻击
- CSRF攻击
- SQL注入
- Windows漏洞
- 密码破解
- 架构安全
- 防火墙
- 隔离网络
- 通过将网络划分成不同的区域,制定出不同区域之间的访问控制策略来控制不同信任程度区域间传送的数据流
- 太贵,很难实现
- 一般还是靠运营商或者云服务商强大的带宽和流量清洗能力
- 防火墙
- 功能安全
- 规模
- 规模带来的复杂度 - 量变带来的质变
- 功能越来越多,复杂度指数级增加
- 数据越来越多
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 stone2paul@gmail.com
文章标题:架构学习-复杂度来源
文章字数:2k
本文作者:Leilei Chen
发布时间:2020-02-04, 12:09:13
最后更新:2020-02-04, 12:09:32
原始链接:https://www.llchen60.com/%E6%9E%B6%E6%9E%84%E5%AD%A6%E4%B9%A0-%E5%A4%8D%E6%9D%82%E5%BA%A6%E6%9D%A5%E6%BA%90/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。