🗒️系统的复杂度
软件系统复杂度的来源
1. 高性能
对性能孜孜不倦的追求是整个人类技术不断发展的根本驱动力。
技术发展带来了性能上的提升,不一定带来复杂度的提升。例如,硬件存储从纸带→磁带→磁盘→SSD,并没有显著带来系统复杂度的增加。因为新技术会逐步淘汰旧技术,这种情况下我们直接用新技术即可,不用担心系统复杂度会随之提升。
只有那些并不是用来取代旧技术,而是开辟了一个全新领域的技术,才会给软件系统带来复杂度,因为软件系统在设计的时候就需要在这些技术之间进行判断选择或者组合。就像汽车的发明无法取代火车,飞机的出现也并不能完全取代火车,所以我们在出行的时候,需要考虑选择汽车、火车还是飞机,这个选择的过程就比较复杂了,要考虑价格、时间、速度、舒适度等各种因素。
软件系统中,为了高性能而带来的复杂度,主要体现在两方面:
单台计算机内部
多台计算机集群
1.1 单机复杂度
计算机内部复杂度最关键的地方就是操作系统。
计算机性能的发展本质上是由硬件发展驱动的,尤其是 CPU 的性能发展。著名的“摩尔定律”表明了 CPU 的处理能力每隔 18 个月就翻一番;而将硬件性能充分发挥出来的关键就是操作系统,所以操作系统本身其实也是跟随硬件的发展而发展的,操作系统是软件系统的运行环境,操作系统的复杂度直接决定了软件系统的复杂度。
操作系统和性能最相关的就是进程和线程。
输入、计算和输出功能
问题:显然人的输入速度远远比不上计算机的运算速度
批处理操作系统:指令清单,即我们常说的任务。为了解决手工操作低效的问题
好处:批处理程序大大提升了处理性能
缺点:计算机一次只能执行一个任务。如果某个任务需要从 I/O 设备(如磁带)读取大量的数据,此时在 I/O 操作的过程中 CPU 其实是空闲的,而这个空闲时间本来是可以进行其它计算的
进程:对应一个任务。每个任务都有自己独立的内存空间,进程间互不相关,由操作系统来调度
分时处理:此时的 CPU 还没有多核和多线程的概念,为了达到多进程并行运行的目的,采取了分时的方式,即把 CPU 的时间分成很多片段,每个片段只能执行某个进程中的指令。虽然从操作系统和 CPU 的角度来说还是串行处理的,但是由于 CPU 的处理速度很快,从用户的角度来看,感觉是多进程在并行处理
进程间的各种通信方式:管道、消息队列、信号量、共享存储等。虽然多进程要求每个任务都有独立的内存空间,进程间互不相关,但从用户的角度来看,两个任务之间能够在运行过程中就进行通信,会让任务设计变得更加灵活高效
缺点:单个进程内部只能串行处理。实际上很多进程内部的子任务并不要求是严格按照时间顺序来执行的,也需要并行处理。所以又发明了线程
线程:是进程内部的子任务,但这些子任务都共享同一份进程数据。为了保证数据的正确性,又发明了互斥锁机制。有了多线程后,操作系统调度的最小单位就变成了线程,而进程变成了操作系统分配资源的最小单位。
问题:多进程多线程虽然能让多任务并行处理的性能大大提升,但本质上还是分时系统,并不能做到时间上真正的并行
为了实现真正意义上的多任务并行,就得让多个 CPU 能够同时执行计算任务。三种解决方案:
SMP,Symmetric Multi-Processor,对称多处理器结构。最常见的,比如流行的多核处理器
NUMA,Non-Uniform Memory Access,非一致存储访问结构
MPP,Massive Parallel Processing,海量并行处理结构
操作系统发展到现在,如果我们要完成一个高性能的软件系统,需要考虑如多进程、多线程、进程间通信、多线程并发等技术点,而且这些技术并不是最新的就是最好的,也不是非此即彼的选择。在做架构设计的时候,需要花费很大的精力来结合业务进行分析、判断、选择、组合,这个过程同样很复杂。举一个最简单的例子:Nginx 可以用多进程也可以用多线程,JBoss 采用的是多线程;Redis 采用的是单进程,Memcache 采用的是多线程,这些系统都实现了高性能,但内部实现差异却很大。
1.2 集群的复杂度
尤其是进入互联网时代后,业务的发展速度远远超过了硬件的发展速度。要支持复杂的业务,必须采用机器集群的方式来达到高性能。
通过大量机器来提升性能,并不仅仅是增加机器这么简单,让多台机器配合起来达到高性能的目的,是一个复杂的任务,我针对常见的几种方式简单分析一下。
任务分配
任务分解
2. 高可用
3. 可扩展性
4. 低成本、安全、规模
Last updated