书接上文
在一个分布式系统(指互相连接并共享数据的节点的集合)中,当涉及到读写操作时,只能保证
一致性(Consistence)
、可用性(Availability)
、分区容错性(Partition Tolerance)
三者中的两个,另外一个必须被牺牲
对某个指定的客户端来说,读操作保证能够返回最新的写操作数据
非故障的节点在合理的时间内返回合理的响应(不是错误和超时的响应)
当出现网络分区(发生丢包、连接中断、拥塞等)后,系统能够继续按预期工作
首先,你肯定是要选P分区容忍性
的,因为网络本身是无法100%可靠的,所以分区是必然的,你也不想网络一点抖动你系统就挂了吧。如果不选分区容忍性
,那么发生分区时,为了保障一致性
,系统要禁止写操作,当发生写操作时返回err,这又和可用性
冲突了,所以理论上你必须选P分区容忍性
。
CP一致性+分区容忍性:前面说了,当发生分区时,为了保障一致性
,要禁止写操作返回err,所以这时候可用性
是不能被满足的,所说CAP只能满足CP。
AP可用性+分区容忍性:为了保障可用性
,发生分区时,底层数据无法同步,必然造成数据的不一致,这时系统还要对外提供服务,所以CAP只能满足AP。
CAP还有一些细节需要注意。
一致性
是不可能完美实现的可用性
和一致性
是可以同时被满足的ACID是数据库管理系统为了保证事务的正确性而提出来的一个理论,包含四个约束:
BASE是指基本可用(Basically Available)
、软状态(Soft State)
、最终一致性(Eventual Consistency)
。其核心思想是即使无法做到强一致性,但可以采用合适的方式达到最终一致性。现实中很多系统大多都是采用的最终一致性,强一致性常见于金融业务。
FMEA(故障模式与影响分析)又称为失效模式与后果分析等,是一套分析和思考的方法。具体分析方法如下:
此方法输出的是一份表格,包含功能点、故障模式、故障影响、严重程度、故障原因、故障概率、风险程度、已有措施、解决措施和后续规划。总结来说就是一份分析报告,列出系统的薄弱点,并提出改进措施,很可能改进之后又会引入新的薄弱点,所以需要不断更新。除此之外也可以当成一份运维手册来看,当发生故障时看看这份表上有没有相应的补救措施。
存储高可用本质都是将数据复制到多个节点,通过冗余来实现高可用。这类方案都要面对的一个问题是复制延迟和中断导致的数据不一致。任何一个存储高可用方案,都要想清楚以下几点:
主机对外提供服务,通过复制通道将数据复制到备机,备机不对外提供服务。发生故障时需要将客户端的请求转到备机上。
缺点是如果主机永久挂了,对于复制延迟和中断造成的数据缺失没啥好的解决方案。由于备机不提供服务,平时会造成资源浪费。
优点就是比较简单,适用于内部管理系统。
跟主备复制类似,但是备机是可以对外提供读服务的。
优点就是机器资源得到有效利用,主机挂了,读操作不受影响
缺点就是如果延迟比较高,写完立即读可能读到旧数据。也比较复杂,需要将不同的操作发给不同的机器
适应于论坛新闻类的业务,读多写少,影响范围可以控制
无论是上面哪种模式,发生故障时都要进行角色的转换。需要有状态的判断机制和倒换策略。例如:
根据状态传递渠道的不同,常见的主备倒换架构有三种形式:
当一台节点存储不下全部数据时,上面的两种方案就用不了了,就要上数据集群了,把数据分散到各个节点上。此方案的复杂点在于如何将数据分配到不同的服务器上,设计时需要考虑以下几点:
既然数据分散到各个节点,那避免不了的问题就是分布式事务
。目前分布式事务算法非常多,但再多的算法也不能彻底解决问题,极端情况下还得看人工。目前常用的分布式事务算法有:
数据分区是指将数据按照一定的规则进行分区,不同分区分布到不同的地理位置上,每个分区存储一部分数据,通过这种方式来规避地理级别的故障。分区规则有很多,你可以选城市分区、国家分区、洲际分区等,一般看业务量决定。同时,即使是数据分区,也要考虑分区数据的备份,万一真发生地理级别的故障,还是要尽可能将数据恢复。一般有以下几种备份规则:
计算高可用的主要目的是当部分节点故障时,服务依然能正常对外提供服务。因此和存储高可用的思路是一致的,就是通过冗余来规避风险。这里复杂度主要体现在任务管理方便,即怎么分发任务
和任务执行失败后怎么处理
的问题。架构一般由任务分配器
+计算节点
组成。
常见的计算高可用架构:
业务高可用主要实现方式就是异地多活,异地多活又分同城异区
、跨城异地
、跨国异地
,具体采用哪种方案需要根据业务量级以及业务重要程度来选择。另外,核心业务内部也分核心数据和非核心数据,所以在选择方案是也可以根据数据重要程度进行进一步划分。
在发生业务故障时,要使用日志记录并做好用户的补偿,降低影响范围和舆论影响程度。
另外针对接口级别的故障,平时发生的概率比较高,我们一般有以下几种应对方案
可拓展架构的主要价值在于后续改动时,能尽量降低开发成本,降低改动范围。一般来说,设计方法有很多,但核心思想就是拆分
,怎么拆各有各的说法,你可以面向流程拆分
,也可以面向服务拆分
,也可以面向功能拆分
。
这是非常常见的架构模式,例如C/S架构、B/S架构、MVC架构等等。平常设计时也会习惯性进行分层,进行逻辑的划分,降低整体的复杂度。划分的原则也很简单,就是要保证各层之间的差异足够清晰,边界足够明显,可读性高
。
但有个缺点就是可能会发生冗余,有时候你只需要调用最底层的一个接口就好,但是为了维持这个分层架构,不得不层次传递,如果各层之间是网络连接,那网络耗时将会大大增加。
SOA是面向服务的架构,现在在传统大企业里面可能比较容易见到。提出的背景是企业内部的IT系统重复建设且效率低下。例如企业里面有很多独立的系统,财务系统、销售系统、HR系统等等,这些系统都需要进行员工的权限管理,也许都要重复开发该能力。
SOA主要有三个概念:
SOA的瓶颈就在ESB上,因为所有服务都要通过它来进行通信。
微服务是大家耳熟能详的老伙计了,在国内的互联网公司,稍微大一点的业务都会采用微服务架构。微服务很容易和SOA混淆,主要区别在于服务粒度不同(SOA粒度比较粗)
、服务通信(SOA使用ESB通信,兼容不同协议,微服务的通信协议是一致的,简单很多)
、服务交付(微服务的交付成本先易后难,微服务越多,越需要更强的管理手段)
、应用场景(SOA适用于改动成本高的企业级系统,微服务适用于快速迭代的互联网系统)
。
采用微服务架构,开发基建一定要跟上,因为随着微服务越来越多,怎么做服务发现,怎么做服务路由,怎么自动部署,怎么排查问题就是实实在在要面对的问题。
那么,微服务要怎么拆分呢,基于什么原则进行拆分?
首先有一个“三个火枪手原则”:
三个火枪手原则:一个微服务三个人负责开发
具体的拆分方法有,可以根据自己的业务特点进行选择:
关于微服务有很多其他经典的书籍可以学习,后续可以展开写写。
就是插件式架构,关键技术有:插件管理
、插件连接
和插件通信
。
应用场景有很多,例如促销规则生成系统,内核就是一个计算逻辑,但是很多商品种类可以封装成插件,新增规则时开发成很低。
一张图就可以说明了,内容深度不大。
前面我们介绍架构设计原则的时候,有一条原则就是“演化原则”。
演化优于一步到位
现在就是演化的时候了。在演化时,我们要注意:
读完收益良多,以前总是觉得架构挺神秘的,奈何没有一个系统的教程入门,网上资料汗牛充栋,根本无从下手,进行系统设计时脑子都是空白的,没有头绪。这本书介绍的挺全面的,很适合扫盲用,适合那些刚接触架构设计的开发人员。
后续可以在这里练练手:系统设计题