架构设计复杂度来源

用户头像
escray
关注
发布于: 2020 年 09 月 03 日
架构设计复杂度来源

极客时间《从零开始学架构》学习笔记

04 | 复杂度来源:高性能



首先把系统跑起来,然后尽可能的做单机性能优化,在单机成为瓶颈时,考虑集群的任务分配和任务分解。



一般人可能并没有机会去接触类似于淘宝或者微信这样量级的架构,从个人而言,我更关注单机性能优化。



除了传统意义上的单机优化,如果把应用部署阿里云这样的云平台上,单机性能优化是否有不同?



开辟新领域的技术,增加了选择或组合的可能,给软件系统带来复杂度。



高性能可以带来良好的用户体验(快),满足业务增长的需要(Google、淘宝、微信)



高性能带来的复杂度分为单机内部和多机集群两方面。



从没有操作系统的简单输入、计算、输出,到批处理,再到由操作系统调度的分时的进程,然后发展出进程间通信(管道、消息队列、信号量、共享存储),接下来进程内部又分出了线程,再加上互斥锁机制操作系统调度的最小单位变成了线程,而进程是操作系统分配资源的最小单位



多进程多线程其实仍然是分时的,为了让多个 CPU 同时工作,又有了三种方案 SMP(Symmetric Multi-Processor,对称多处理器结构)、NUMA(Non-Uniform Memory Access,非一致存储访问结构)、MPP(Massive Parallel Processing,海量并行结构)——不明觉厉



其实操作系统帮助我们屏蔽的很多复杂性。



Nginx 可以用多进程或者多线程,JBoss 多线程,Redis 单进程,Memcache 多线程……都是高性能,但是差别很大。



当单机性能无法支撑业务复杂度时,就要采用集群的方式,从任务分配到任务分解,尽可能提高整体性能。



现在比较流行的微服务有点类似于任务分解?



最终决定业务处理性能的还是业务逻辑本身,性能在理论上有一个上限。高性能并没有绝对标准,要从业务出发,结合行业经验判断。



05 | 复杂度来源:高可用



High availability (HA) is a characteristic of a system, which aims to ensure an agreed level of operational performance, usually uptime, for a higher than normal period.



高可用意味着无中断,系统高可用方案本质上都是通过“冗余”实现。



高性能增加机器的目的在于“扩展”处理性能;高可用增加机器的目的在于“冗余”处理单元。



有没有可能增加机器同时满足高性能和高可用?感觉上高性能和高可用是不同的两个衡量维度,有可能在降低性能指标的情况下保证高可用?



计算高可用将计算分配到不同主机,有双机(主备:冷备、热备、温备;主主)和集群,ZooKeeper 采用 1 主多备,Memcached 全主 0 备。



存储高可用将存储冗余到不同主机,与计算高可用不同,数据转移需要经过线路传输,有物理上的传输速度限制,同时传输线路本身也可能有问题(中断、拥塞、异常),从而造成延时。存储高可用的难点不在于如何备份数据,而在于如何减少或者规避桑树不一致对业务造成的影响。



分布式领域的 CAP 定义,从理论上论证了存储高可用的复杂度。存储高可用不可能同时满足“一致性、可用性、分区容错性”,最多满足其中两个。



计算高可用和存储高可用都建立在状态决策的基础上,与此同时,通过冗余来实现的高可用系统,状态决策本质上就不可能做到完全正确。无论是独裁式、协商式或者民主式,状态决策都可能出现问题(这个和人类社会很像),需要结合业务,进行分析、判断和选择。



通常情况下,高可用要比高性能复杂一些,需要考虑的场景更多(如果不可用了,自然也就没有性能)。4 个 9 的可用性(99.99%)意味着系统全年宕机时间不超过 53 分钟。



Zookeeper 使用 ZAB 算法实现选举。



高可用是指正常提供服务的概率,主要和故障恢复时间有关;高可靠是指出问题的概率,主要和故障次数有关。



06 | 复杂度来源:可扩展性



Scalability is the property of a system to handle a growing amount of work by adding resources to the system. … In computing, scalability is characteristic of computers, networks, algorithms, networking protocols, programs and application.



面向对象和设计模式都试图解决扩展性带来的问题,但是想要做到“正确预测变化、完美封装变化”难度非常大。



不能每个设计点都考虑可扩展性,也不能完全不考虑;与此同时,所有的预测都有出错的可能。



即使预测正确,那么采用合适的解决方案,也很重要。一种是将变化封装在一个变化层,难点在于拆分变化层和稳定层,并且设计两层之间的借口;另一种是提炼出稳定的抽象层。然后根据具体业务需要定制开发抽象层。



装饰者模式的经典例子 TextView,其实只要能看懂那张类关系图,那么也就明白了什么是装饰者模式。我觉的难点在于 Decorator 类继承并且聚合了 Commponent 类,并且有多个 ConcreteDecorator 类继承 Decorator 类并实现 Operatorion() 方法。



老师在留言里面提到,“设计的时候考虑可扩展性,但是如果代价比较大,就展示不做,有需要时再重构”,这个比较实用。



之前做过的系统对于可扩展没有什么要求,实在不行的时候,就会考虑推到重来。



可扩展性并不想前面提到的高性能和高可用那么容易衡量,因为扩展的可能性还是要小一些,或者说可扩展性并不是特别的明显。



按照专栏里面的说法,设计模式好像更多的是考虑可扩展性,感觉上似乎对于高性能和高可用意义不大。但是反过来,对于普通的应用开发者来说,是不是遇到扩展性问题(或者需求变化)的可能性要远大于高性能或者高可用?



07 | 复杂度来源:低成本、安全、规模



以前其实是没有成本意识的。



低成本与高性能和高可用在本质上是有冲突的,低成本一般不会成为架构设计的首要目标,但是成本往往会成为架构设计的制约。



我自己的目标是成为“经济适用型”的架构师,那么就需要用合适的技术和合理的创新来实现性价比,进而需要了解业界已有的成熟架构,从中选择适用的设计。



相比创造新技术来说,引入新技术并且将新技术与已有技术结合,相对来说还是要容易一些。



惭愧的说,也没有想过架构安全的事。



因为以前的开发环境基本上是在一个封闭的内网环境,面对的也大多是“小白”用户(现在可能有一些高手了),所以不需要在安全上考虑太多,最多是使用框架自带的一些功能安全选项,比如避免 SQL 注入。



架构安全以前是由专人负责,其实就是网络以及防火墙的配置。



从专栏文章来看,我觉得架构师需要有安全意识(作为程序员也一样),但是安全的事情可能还是需要专业的人去处理。



我以前面对的系统可能勉强可以算的上是中等规模,功能比较多,数据量中等,应该还没有到“量变引起质变”的时候,但是应对起来似乎也比较勉强。



顺便回答思考题,这个系统的复杂度主要来源在于高可靠,一般是要求 24 × 7 不停机的,但是实际上估计达不到 4 个 9 的可靠性。



看到留言里面提到了“可伸缩性”,如果是租用数据中心的存储和计算资源,那么可伸缩性可以省钱,是有意义的;如果是自建系统,那么“可伸”类似于“可扩展”,“可缩”的意义就不大了,很难在自建环境中调配使用。


这四篇专栏文章讲述了架构设计复杂度的来源,相对重要的高性能、高可用和可扩展,也是后面整个课程的脉络,以及进行架构设计的考量维度。



参考资料:架构设计复杂度的 6 个来源

发布于: 2020 年 09 月 03 日 阅读数: 35
用户头像

escray

关注

大龄程序员 CSD 求职中…… 2017.11.19 加入

想找一个技术类职位,最好 Remote ,欢迎各位大佬来撩

评论

发布
暂无评论
架构设计复杂度来源