什么是分布式系统?绝大多数词典、百科给出的解释是相同的:
分布式系统(distributedsystem)是建立在网络之上的软件系统。正是因为其软件的特性,所以分布式系统具有高度的内聚性和透明性。因此,网络和分布式系统之间的区别更多的在于高层软件(特别是操作系统),而不是硬件。
内聚性是指每一个数据库分布节点高度自治,有本地的数据库管理系统。
透明性是指每一个数据库分布节点对用户的应用来说都是透明的,看不出是本地还是远程。
在一个分布式系统中,一组独立的计算机展现给用户的是一个统一的整体,就好像是一个系统似的。系统拥有多种通用的物理和逻辑资源,可以动态的分配任务,分散的物理和逻辑资源通过计算机网络实现信息交换。系统中存在一个以全局的方式管理计算机资源的分布式操作系统。通常,对用户来说,分布式系统只有一个模型或范型。在操作系统之上有一层软件中间件(middleware)负责实现这个模型。一个著名的分布式系统的例子是万维网(World Wide Web),在万维网中,所有的一切看起来就好像是一个文档(Web页面)一样。
简洁却专业的解释了分布式系统,但让专业知识不够硬的我倍感压力,总结在操作系统中的学习经验,将分布式系统简单的解释成了一句话:
一个分布式系统由一组计算机协同工作组成,目的是利用更多的机器,处理更多的数据。
但需要明确的是,只有当单个节点的处理能力无法满足计算任务,且硬件的提升代价超出能力范围(加内存、加磁盘、使用更好的CPU),程序本身也无法进一步优化的时候,才需要考虑到分布式系统。因为分布式系统多节点之间通过网络通信的拓扑结构会引入许多单机系统中没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。所以分布式系统的本质就是用更加复杂的结构换取更加有效的计算能力。
上述提到了分布式系统中存在着些许的问题,可以将这些问题在大体上分为三类:
一、异构的机器与网络
分布式系统中的各机器配置不尽相同,在这些机器上运行的服务也可能由不同的语言以及架构来实现的,因此处理的能力也可能不一致;节点间通过网络连接,而不同网络运营商提供的网络的带宽、延时、丢包率等网络配置又不一样。那通过什么手段能够保证所有机器协作共同的完成目标:中间件。
中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的。
二、普遍的节点故障
虽然单个节点的故障概率较低,但当节点的数目达到一定规模时,某一节点出故障的概率就会变高。分布式系统需要保证故障发生时,系统仍然是可以正确运行的,这就需要去监控各个节点的实时状态,在节点故障的情况下将该节点负责的计算任务及时的转移到其他适合的节点上。
三、不可靠的网络
节点之间是通过网络通信的,而网络通常是不可靠的。可能的网络问题包括:网络分割、延时、丢包、乱序等。
总而言之,分布式系统的问题绝大多数都来自不确定性,当然单机系统也会面临:不确定计算机什么时候宕机,不确定硬件什么时候损坏,不确定每次网络通信要延迟多久等这类问题。但分布式的规模放大了这个不确定性,所以需要诸多的分布式理论、协议来保证在这种不确定性的情况下,系统还能够继续正常的工作。
针对上述的问题,提出了以下四种解决方案/策略:
1、重试机制
在网络交互过程中,一般都是发起RPC或者HTTP协议,可能会遇到请求超时而失败的情况。一般的导致原因是由于网络抖动(暂时的网络变更导致包不可达,比如拓扑变更)或对端结束服务而导致的。这时一般的处理逻辑是将请求包放在一个重试循环块里,同时为了防止网络堵塞,循环块也应该设置一个持续时间,到时自动结束。
此种模式可以防止因网络暂时抖动而发送失败的情况,因为一般网络抖动的持续时间很短,在进行多次重试后,就能够请求成功。但不能防止对端长时间不能连接(网络问题或进程问题)。
2、心跳机制
以固定的频率向其他节点汇报当前自身节点的状态。当收到一个节点的心跳时,可以认为该节点和当前网络拓扑是良好的。当然,在心跳汇报时,一般也要携带一些附加信息如:状态、元数据等,以便管理。
但心跳机制也不是万能的,收到心跳时可以确认OK该节点无异常,但是收不到心跳时不能够反推出该节点不存在或挂掉,可能是因为网络原因导致链路不通但是节点依旧在正常工作。
所以心跳机制只能告诉你节点正处于正常的状态,而不能发现节点是否异常,是否还在继续服务。
3、副本
副本指的是针对一份数据的多份冗余拷贝,在不同的节点上持久化同一份数据,当某一个节点的数据丢失时,可以从其对应的副本上获取数据。数据副本是分布式系统解决数据丢失异常的唯一途径。当然对多份副本的写入会产生一致性与可用性的相关问题,比如规定副本数为3,同步写3份,会产生3次I/O的性能分配问题。再比如先同步写1份,然后异步写2份,对初始数据进行更新,当后2份没有完成此次更新依旧保留了上一次的内容时被其他模块读取,这就会产生一致性的问题,。
4、中心化/无中心化
两种系统模型:
(1)存在中心节点,例如mysql的MSS单主双从、MongDB Master、HDFS NameNode、MapReduce JobTracker等,有1个或几个节点充当整个系统的核心元数据及节点管理工作,其他节点都和中心节点交互。这种方式的优点显而易见,数据和管理高度统一集中在一个地方,容易聚合,且简单可行。由于模块的高度集中其缺点也很明显,容易形成性能瓶颈,并且如果中心节点出现异常,就会导致整个系统瘫痪。
(2)去中心化,例如cassandra、zookeeper,系统中不存在中心节点,节点间进行广播通信依次进行合作来完成任务。优点在于如果某一个或几个节点出现异常,对系统整体不会有直接影响,只有局部是不可用的状态。缺点是协议复杂,需要各个节点间实时进行信息的同步。