分布式系统是由一组经过网络进行通讯、为了完成共同的任务而协调工做的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机没法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据。html
首先须要明确的是,只有当单个节点的处理能力没法知足日益增加的计算、存储任务的时候,且硬件的提高(加内存、加磁盘、使用更好的CPU)高昂到得不偿失的时候,应用程序也不能进一步优化的时候,咱们才须要考虑分布式系统。mysql
由于,分布式系统要解决的问题自己就是和单机系统同样的,而因为分布式系统多节点、经过网络通讯的拓扑结构,会引入不少单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。。。web
在不少文章中,主要讲分布式系统分为分布式计算(computation)与分布式存储(storage)。计算与存储是相辅相成的,计算须要数据,要么来自实时数据(流数据),要么来自存储的数据;而计算的结果也是须要存储的。在操做系统中,对计算与存储有很是详尽的讨论,分布式系统只不过将这些理论推广到多个节点罢了。redis
那么分布式系统怎么将任务分发到这些计算机节点呢,很简单的思想,分而治之,即分片(partition)。对于计算,那么就是对计算任务进行切换,每一个节点算一些,最终汇总就好了,这就是MapReduce的思想;对于存储,更好理解一下,每一个节点存一部分数据就好了。当数据规模变大的时候,Partition是惟一的选择,同时也会带来一些好处:spring
(1)提高性能和并发,操做被分发到不一样的分片,相互独立sql
(2)提高系统的可用性,即便部分分片不能用,其余分片不会受到影响docker
理想的状况下,有分片就好了,但事实的状况却不大理想。缘由在于,分布式系统中有大量的节点,且经过网络通讯。单个节点的故障(进程crash、断电、磁盘损坏)是个小几率事件,但整个系统的故障率会随节点的增长而指数级增长,网络通讯也可能出现断网、高延迟的状况。在这种必定会出现的“异常”状况下,分布式系统仍是须要继续稳定的对外提供服务,即须要较强的容错性。最简单的办法,就是冗余或者复制集(Replication),即多个节点负责同一个任务,最为常见的就是分布式存储中,多个节点复杂存储同一份数据,以此加强可用性与可靠性。同时,Replication也会带来性能的提高,好比数据的locality能够减小用户的等待时间。数据库
下面这种来自Distributed systems for fun and profit 的图形象生动说明了Partition与Replication是如何协做的。apache
Partition和Replication是解决分布式系统问题的一记组合拳,不少具体的问题均可以用这个思路去解决。但这并非银弹,每每是为了解决一个问题,会引入更多的问题,好比为了可用性与可靠性保证,引用了冗余(复制集)。有了冗余,各个副本间的一致性问题就变得很头疼,一致性在系统的角度和用户的角度又有不一样的等级划分。若是要保证强一致性,那么会影响可用性与性能,在一些应用(好比电商、搜索)是难以接受的。若是是最终一致性,那么就须要处理数据冲突的状况。CAP、FLP这些理论告诉咱们,在分布式系统中,没有最佳的选择,都是须要权衡,作出最合适的选择。django
2、分布式系统挑战
分布式系统须要大量机器协做,面临诸多的挑战:
第一,异构的机器与网络:
分布式系统中的机器,配置不同,其上运行的服务也可能由不一样的语言、架构实现,所以处理能力也不同;节点间经过网络链接,而不一样网络运营商提供的网络的带宽、延时、丢包率又不同。怎么保证你们齐头并进,共同完成目标,这四个不小的挑战。
第二,广泛的节点故障:
虽然单个节点的故障几率较低,但节点数目达到必定规模,出故障的几率就变高了。分布式系统须要保证故障发生的时候,系统仍然是可用的,这就须要监控节点的状态,在节点故障的状况下将该节点负责的计算、存储任务转移到其余节点
第三,不可靠的网络:
节点间经过网络通讯,而网络是不可靠的。可能的网络问题包括:网络分割、延时、丢包、乱序。
相比单机过程调用,网络通讯最让人头疼的是超时:节点A向节点B发出请求,在约定的时间内没有收到节点B的响应,那么B是否处理了请求,这个是不肯定的,这个不肯定会带来诸多问题,最简单的,是否要重试请求,节点B会不会屡次处理同一个请求。
总而言之,分布式的挑战来自不肯定性,不肯定计算机何时crash、断电,不肯定磁盘何时损坏,不肯定每次网络通讯要延迟多久,也不肯定通讯对端是否处理了发送的消息。而分布式的规模放大了这个不肯定性,不肯定性是使人讨厌的,因此有诸多的分布式理论、协议来保证在这种不肯定性的状况下,系统还能继续正常工做。
并且,不少在实际系统中出现的问题,来源于设计时的盲目乐观,以为这个、那个应该不会出问题。Fallacies_of_distributed_computing颇有意思,介绍了分布式系统新手可能的错误的假设:
The network is reliable.
Latency is zero.
Bandwidth is infinite.
The network is secure.
Topology doesn't change.
There is one administrator.
Transport cost is zero.
The network is homogeneous.
刘杰在《分布式系统原理介绍》中指出,处理这些异常的最佳原则是:在设计、推导、验证分布式系统的协议、流程时,最重要的工做之一就是思考在执行流程的每一个步骤时一旦发生各类异常的状况下系统的处理方式及形成的影响。
3、分布式系统特性与衡量标准
透明性:使用分布式系统的用户并不关心系统是怎么实现的,也不关心读到的数据来自哪一个节点,对用户而言,分布式系统的最高境界是用户根本感知不到这是一个分布式系统,在《Distributed Systems Principles and Paradigms》一书中,做者是这么说的:
A distributed system is a collection of independent computers that appears to its users as a single coherent system.
可扩展性:分布式系统的根本目标就是为了处理单个计算机没法处理的任务,当任务增长的时候,分布式系统的处理能力须要随之增长。简单来讲,要比较方便的经过增长机器来应对数据量的增加,同时,当任务规模缩减的时候,能够撤掉一些多余的机器,达到动态伸缩的效果
可用性与可靠性:通常来讲,分布式系统是须要长时间甚至7*24小时提供服务的。可用性是指系统在各类状况对外提供服务的能力,简单来讲,能够经过不可用时间与正常服务时间的必知来衡量;而可靠性而是指计算结果正确、存储的数据不丢失。
高性能:无论是单机仍是分布式系统,你们都很是关注性能。不一样的系统对性能的衡量指标是不一样的,最多见的:高并发,单位时间内处理的任务越多越好;低延迟:每一个任务的平均时间越少越好。这个其实跟操做系统CPU的调度策略很像
一致性:分布式系统为了提升可用性可靠性,通常会引入冗余(复制集)。那么如何保证这些节点上的状态一致,这就是分布式系统不得不面对的一致性问题。一致性有不少等级,一致性越强,对用户越友好,但会制约系统的可用性;一致性等级越低,用户就须要兼容数据不一致的状况,但系统的可用性、并发性很高不少。
4、分布式系统下的组件、协议、理论
经过一次用户请求
一、域名机器负载均衡
用户使用Web、APP、SDK,经过HTTP、TCP链接到系统。在分布式系统中,为了高并发、高可用,通常都是多个节点提供相同的服务。那么,第一个问题就是具体选择哪一个节点来提供服务,这个就是负载均衡(load balance)。负载均衡的思想很简单,但使用很是普遍,在分布式系统、大型网站的方方面面都有使用,或者说,只要涉及到多个节点提供同质的服务,就须要负载均衡。
域名系统一般用途是将域名解析成IP地址(没法解析到IP对应的端口)。开发申请域名的时候,确认是否须要分配VIP:
若须要:域名会解析到VIP上,而后经过负载均衡服务将请求分发到业务服务器上。
若不须要:域名将直接解析到服务器上,当服务器宕机,须要域名所属人员经过dns自助服务将服务器从域名解析上删除。
二、负载层缓存以及应用层缓存
经过负载均衡找到一个节点,接下来就是真正处理用户的请求,请求有可能简单,也有可能很复杂。简单的请求,好比读取数据,那么极可能是有缓存的,即分布式缓存,若是缓存没有命中,那么须要去数据库拉取数据。对于复杂的请求,可能会调用到系统中其余的服务。
三、系统内RPC、异步请求、并发处理
承上,假设服务A须要调用服务B的服务,首先两个节点须要通讯,网络通讯都是创建在TCP/IP协议的基础上,可是,每一个应用都手写socket是一件冗杂、低效的事情,所以须要应用层的封装,所以有了HTTP、FTP等各类应用层协议。当系统越发复杂,提供大量的http接口也是一件困难的事情。所以,有了更进一步的抽象,那就是RPC(remote produce call),是的远程调用就跟本地过程调用同样方便,屏蔽了网络通讯等诸多细节,增长新的接口也更加方便。
四、分布式事务
一个请求可能包含诸多操做,即在服务A上作一些操做,而后在服务B上作另外一些操做。好比简化版的网络购物,在订单服务上发货,在帐户服务上扣款。这两个操做须要保证原子性,要么都成功,要么都不操做。这就涉及到分布式事务的问题,分布式事务是从应用层面保证一致性:某种守恒关系。
五、服务注册与发现
上面说道一个请求包含多个操做,其实就是涉及到多个服务,分布式系统中有大量的服务,每一个服务又是多个节点组成。那么一个服务怎么找到另外一个服务(的某个节点呢)?通讯是须要地址的,怎么获取这个地址,最简单的办法就是配置文件写死,或者写入到数据库,但这些方法在节点数据巨大、节点动态增删的时候都不大方便,这个时候就须要服务注册与发现:提供服务的节点向一个协调中心注册本身的地址,使用服务的节点去协调中心拉取地址。
从上能够看见,协调中心提供了中心化的服务:以一组节点提供相似单点的服务,使用很是普遍,好比命令服务、分布式锁。协调中心最出名的就是chubby,zookeeper。
六、日志、MQ消息
回到用户请求这个点,请求操做会产生一些数据、日志,一般为信息,其余一些系统可能会对这些消息感兴趣,好比个性化推荐、监控等,这里就抽象出了两个概念,消息的生产者与消费者。那么生产者怎么讲消息发送给消费者呢,RPC并非一个很好的选择,由于RPC确定得指定消息发给谁,但实际的状况是生产者并不清楚、也不关心谁会消费这个消息,这个时候消息队列就出马了。简单来讲,生产者只用往消息队列里面发就好了,队列会将消息按主题(topic)分发给关注这个主题的消费者。消息队列起到了异步处理、应用解耦的做用。
七、离线数据、实时数据
上面提到,用户操做会产生一些数据,这些数据忠实记录了用户的操做习惯、喜爱,是各行各业最宝贵的财富。好比各类推荐、广告投放、自动识别。这就催生了分布式计算平台,好比Hadoop,Storm等,用来处理这些海量的数据。
八、分布式存储
最后,用户的操做完成以后,用户的数据须要持久化,但数据量很大,大到按个节点没法存储,那么这个时候就须要分布式存储:将数据进行划分放在不一样的节点上,同时,为了防止数据的丢失,每一份数据会保存多分。传统的关系型数据库是单点存储,为了在应用层透明的状况下分库分表,会引用额外的代理层。而对于NoSql,通常自然支持分布式。
5、分布式架构的演进
一、初始阶段架构
初始阶段 的小型系统 应用程序、数据库、文件等全部的资源都在一台服务器上通俗称为LAMP
特征:应用程序、数据库、文件等全部的资源都在一台服务器上。
随着系统访问量的再度增长,webserver机器的压力在高峰期会上升到比较高,这个时候开始考虑增长一台webserver
特征:应用程序、数据库、文件分别部署在独立的资源上。
特征:多台服务器经过负载均衡同时向外部提供服务,解决单台服务器处理能力和存储空间上限的问题。
描述:使用集群是系统解决高并发、海量数据问题的经常使用手段。经过向集群中追加资源,使得服务器的负载压力不在成为整个系统的瓶颈。
特征:采用CDN和反向代理加快系统的 访问速度。
描述:为了应付复杂的网络环境和不一样地区用户的访问,经过CDN和反向代理加快用户访问的速度,同时减轻后端服务器的负载压力。CDN与反向代理的基本原理都是缓存。
分库后查询仍然会有些慢,因而按照分库的思想开始作分表的工做
特征:数据库采用分布式数据库,文件系统采用分布式文件系统。
描述:任何强大的单一服务器都知足不了大型系统持续增加的业务需求,数据库读写分离随着业务的发展最终也将没法知足需求,须要使用分布式数据库及分布式文件系统来支撑。
分布式数据库是系统数据库拆分的最后方法,只有在单表数据规模很是庞大的时候才使用,更经常使用的数据库拆分手段是业务分库,将不一样的业务数据库部署在不一样的物理服务器上。
特征:系统引入NoSQL数据库及搜索引擎。
描述:随着业务愈来愈复杂,对数据存储和检索的需求也愈来愈复杂,系统须要采用一些非关系型数据库如NoSQL和分数据库查询技术如搜索引擎。应用服务器经过统一数据访问模块访问各类数据,减轻应用程序管理诸多数据源的麻烦。
特征:公共的应用模块被提取出来,部署在分布式服务器上供应用服务器调用。
描述:随着业务越拆越小,应用系统总体复杂程度呈指数级上升,因为全部应用要和全部数据库系统链接,最终致使数据库链接资源不足,拒绝服务。
简化的分布式系统架构图
6、组件
Nginx:高性能、高并发的web服务器;功能包括负载均衡、反向代理、静态内容缓存、访问控制;工做在应用层
LVS: Linux virtual server,基于集群技术和Linux操做系统实现一个高性能、高可用的服务器;工做在网络层
Java:Tomcat,Apache,Jboss
Python:gunicorn、uwsgi、twisted、webpy、tornado
SOA、微服务spring cloud、spring boot,django
docker,kubernetes
memcache、redis等
zookeeper、etcd等
zookeeper使用了Paxos协议Paxos是强一致性,高可用的去中心化分布式。zookeeper的使用场景很是普遍,以后细讲。
grpc、dubbo、brpc
dubbo是阿里开源的Java语言开发的高性能RPC框架,在阿里系的诸多架构中,都使用了dubbo + spring boot
kafka、rabbitMQ、rocketMQ、QSP
消息队列的应用场景:异步处理、应用解耦、流量削锋和消息通信
storm、akka
hadoop、spark
PS: apark、akka、kafka都是scala语言写的,看到这个语言仍是很牛逼的
cobar也是阿里开源的,在阿里系中使用也很是普遍,是关系型数据库的sharding + replica 代理
mysql、oracle、MongoDB、HBase
elasticsearch、solr
rsyslog、elk、flume
Hadoop 的HDFS ,还有 google的 GFS , 淘宝的 TFS
书籍推荐
大型分布式网站架构设计与实践
http://item.jd.com/11529266.html
大型网站技术架构:核心原理与案例分析
http://item.jd.com/11322972.html
大型网站系统与Java中间件实践
http://item.jd.com/11449803.html
分布式Java应用:基础与实践
http://item.jd.com/10144196.html
参看地址:
http://www.cnblogs.com/xybaby/p/7787034.html
https://www.cnblogs.com/my376908915/p/6813321.html