分布式系统特征及解决方案node
1、可扩展性
2、可用性
3、一致性
4、高性能算法
一个大型网站就是一个分布式系统,包含诸多组件,这些组件是分布式系统的组成部分;而我如今认为,一个大型网站包含诸多组件,每个组件都是一个分布式系统,好比分布式存储就是一个分布式系统,消息队列就是一个分布式系统。mongodb
可扩展性、高性能、高可用、一致性。这几个特性也是分布式系统的衡量指标,正是为了在不一样的程度上知足这些特性(或者说达到这些指标),才会设计出各类各样的算法、协议,而后根据业务的需求在这些特性间平衡。缓存
为何要知足这些特性,要知足这些特性须要解决什么问题,有什么好的解决方案。服务器
1、可扩展性
可扩展性是指当系统的任务(work)增长的时候,经过增长资源来应对任务增加的能力。可扩展性是任何分布式系统必备的特性,这是由分布式系统的概念决定的:
分布式系统是由一组经过网络进行通讯、为了完成共同的任务而协调工做的计算机节点组成的系统
分布式系统的出现是为了解决单个计算机没法完成的计算、存储任务。那么当任务规模增长的时候,必然就须要添加更多的节点,这就是可扩展性。
扩展性的目标是使得系统中的节点都在一个较为稳定的负载下工做,这就是负载均衡,固然,在动态增长节点的时候,须要进行任务(多是计算,多是数据存储)的迁移,以达到动态均衡。网络
那么首先要考虑的问题就是,如何对任务进行拆分,将任务的子集分配到每个节点,咱们称这个过程问题Partition(Sharding)。关于Partition,其实我在《带着问题学习分布式系统之数据分片 》一文中有详细介绍,这里进行概括总结。并发
第一:分片分式,即按照什么算法对任务进行拆分
常见的算法包括:哈希(hash),一致性哈希(consistency hash),基于数据范围(range based)。每一种算法有各自的优缺点,也就有各自的适用场景。负载均衡
第二:分片的键,partition key
partition key是数据的特征值,上面提到的任何分片方式都依赖于这个partition key,那么该如何选择呢
partition key会影响到任务在分片之间的均衡,并且一些系统中(mongodb)几乎是不能从新选择partition key的,所以在设计的时候就得想清楚异步
第三:分片的额外好处
提高性能和并发:不一样的请求分发到不一样的分片
提升可用性:一个分片挂了不影响其余的分片分布式
第四:分片带来的问题
若是一个操做须要跨越多个分片,那么效率就会很低下,好比数据中的join操做
第五:元数据管理
元数据记录了分片与节点的映射关系、节点状态等核心信息,分布式系统中,有专门的节点(节点集群)来管理元数据,咱们称之为元数据服务器。元数据服务器有如下特色:
高性能:cache
高可用:冗余 加 快速failover
强一致性(同时只有一个节点对外提供服务)
第六:任务的动态均衡
为了达到动态均衡,须要进行数据的迁移,如何保证在迁移的过程当中保持对外提供服务,这也是一个须要精心设计的复杂问题。
2、可用性
可用性(Availability)是系统不间断对外提供服务的能力,可用性是一个度的问题,最高目标就是7 * 24,即永远在线。但事实上作不到的,通常是用几个9来衡量系统的可用性,以下如所示:
也就是若是要达到4个9的可用度(99.99%),那么一年之中只能有52.6分钟不可用,这是个巨大的挑战
为何分布式系统中必需要考虑可用性呢,这是由于分布式系统中故障的几率很高。分布式系统由大量异构的节点和网络组成,节点可能会crash、断电、磁盘损坏,网络可能丢包、延迟、网络分割。系统的规模放大了出故障的几率,所以分布式系统中,故障是常态。那么分布式系统的其中一个设计目标就是容错,在部分故障的状况下仍然对外提供服务,这就是可用性。
冗余是提升可用性、可靠性的法宝。
冗余就是说多个节点负责相同的任务,在须要状态维护的场景,好比分布式存储中使用很是普遍。在分布式计算,如MapReduce中,当一个worker运行异常缓慢时,master会将这个worker上的任务从新调度到其它worker,以提升系统的吞吐,这也算一种冗余。但存储的冗余相比计算而言要复杂许多,所以主要考虑存储的冗余。
维护同一份数据的多个节点称之为多个副本。咱们考虑一个问题,当向这个副本集写入数据的时候,怎么保证并发状况下数据的一致性,是否有一个节点有决定更新的顺序,这就是中心化、去中心话副本协议的区别。
中心化与去中心化
中心化就是有一个主节点(primary master)负责调度数据的更新,其优势是协议简单,将并发操做转变为顺序操做,缺点是primar可能成为瓶颈,且在primary故障的时候从新选举会有一段时间的不可用。
去中心化就是全部节点地位平等,都可以发起数据的更新,优势是高可用,缺点是协议复杂,要保证一致性很难。
提到去中心化,比较有名的是dynamo,cassandra,使用了quorum、vector clock等算法来尽可能保证去中心化环境下的一致性。对于去中心化这一块,目前还没怎么学习,因此下面主要讨论中心化副本集。对于中心化副本协议,我在《带着问题学习分布式之中心化复制集》一文中也有详细介绍,这里简单概括总结。
节点更新策略
primary节点到secondary节点的数据时同步仍是异步,即客户端是否须要等待数据落地到副本集中的全部节点。
同步的优势在于强一致性,可是可用性和性能(响应延迟)比较差;异步则相反。
数据流向
即数据是如何从Primary节点到secondary节点的,有链式和主从模式。
链式的优势时充分利用网络带宽,减轻primary压力,但缺点是写入延迟会大一些。GFS,MongoDB(默认状况下)都是链式。
部分节点写入异常
理论上,副本集中的多个节点的数据应该保持一致,所以多个数据的写入理论上应该是一个事务:要么都发生,要么都不发生。可是分布式事务(如2pc)是一个复杂的、低效的过程,所以副本集的更新通常都是best effort 1pc,若是失败,则重试,或者告诉应用自行处理。
primary的选举
在中心化副本协议中,primary节点是如何选举出来的,当primary节点挂掉以后,又是如何选择出新的primary节点呢,有两种方式:自治系统,依赖其余组件的系统。(ps,这两个名字是我杜撰的 。。。)
所谓的自治系统,就是节点内部自行投票选择,好比mongodb,tfs,zookeeper
依赖其余组件的系统,是指primary由副本集以后的组件来任命,好比GFS中的primary由master(GFS的元数据服务器)任命,hdfs的元数据namenode由zookeeper心跳选出。
secondary是否对外提供服务(读服务)
中心化复制集中,secondary是否对外提供读服务,取决于系统对一致性的要求。
好比前面介绍到节点更新策略时,多是异步的,那么secondary上的数据相比primary会有必定延迟,从secondary上读数据的话没法知足强一致性要求。
好比元数据,须要强一致性保证,因此通常都只会从primary读数据。并且,通常称主节点为active(master),从节点为standby(slave)。在这种状况下,是经过冗余 加上 快速的failover来保证可用性。
3、一致性
为了高可用性,引入了冗余(副本)机制,而副本机制就带来了一致性问题。固然,若是没有冗余机制,或者不是数据(状态)的冗余,那么不会出现一致性问题,好比MapReduce。
一致性与可用性在分布式系统中的关系,已经有足够的研究,造成了CAP理论。CAP理论就是说分布式数据存储,最多只能同时知足一致性(C,Consistency)、可用性(A, Availability)、分区容错性(P,Partition Tolerance)中的二者。但一致性和可用性都是一个度的问题,是0到1,而不是只有0和1两个极端。
一致性从系统的角度和用户的角度有不一样的等级。
系统角度的一致性
强一致性、弱一致性、最终一致性
用户角度的一致性
单调读一致性,单调写一致性,读后写一致性,写后读一致性
4、高性能
正式由于单个节点的scale up不能完成任务,所以咱们才须要scale out,用大量的节点来完成任务,分布式系统的理想目标是任务与节点按必定的比例线性增加。
衡量指标
高并发
高吞吐
低延迟
不一样的系统关注的核心指标不同,好比MapReduce,自己就是离线计算,无需低延迟
可行的办法 单个节点的scaleup 分片(partition) 缓存:好比元数据 短事务