到底什么是分布式系统,该如何学习

点击上方“互扯程序”,选择“置顶公众号”java

优秀文章,第一时间送达!mysql

KS

Knowledge Sharinglinux

知识分享web

    如今是资源共享的时代,一样也是知识分享的时代,若是你以为本文能学到知识,请把知识与别人分享。redis



正文spring


不少人说,分布式系统是“入门容易,深刻难”,我以前的学习也只算是管中窥豹,只见得其中一斑。所以,一致但愿能对分布式系统有一个更全面的认识,至少可以把分布式系统中的各个技术、理论串起来,了解他们在分布式系统分别解决什么问题,有哪些优秀的实现。sql


640?wx_fmt=png

 


什么是分布式系统


分布式系统是由一组经过网络进行通讯、为了完成共同的任务而协调工做的计算机节点组成的系统。分布式系统的出现是为了用廉价的、普通的机器完成单个计算机没法完成的计算、存储任务。其目的是利用更多的机器,处理更多的数据。docker


首先须要明确的是,只有当单个节点的处理能力没法知足日益增加的计算、存储任务的时候,且硬件的提高(加内存、加磁盘、使用更好的CPU)高昂到得不偿失的时候,应用程序也不能进一步优化的时候,咱们才须要考虑分布式系统。由于,分布式系统要解决的问题自己就是和单机系统同样的,而因为分布式系统多节点、经过网络通讯的拓扑结构,会引入不少单机系统没有的问题,为了解决这些问题又会引入更多的机制、协议,带来更多的问题。。。数据库


在不少文章中,主要讲分布式系统分为分布式计算(computation)与分布式存储(storage)。计算与存储是相辅相成的,计算须要数据,要么来自实时数据(流数据),要么来自存储的数据;而计算的结果也是须要存储的。在操做系统中,对计算与存储有很是详尽的讨论,分布式系统只不过将这些理论推广到多个节点罢了。django


那么分布式系统怎么将任务分发到这些计算机节点呢,很简单的思想,分而治之,即分片(partition)。对于计算,那么就是对计算任务进行切换,每一个节点算一些,最终汇总就好了,这就是MapReduce的思想;对于存储,更好理解一下,每一个节点存一部分数据就好了。当数据规模变大的时候,Partition是惟一的选择,同时也会带来一些好处:


  • 提高性能和并发,操做被分发到不一样的分片,相互独立

  • 提高系统的可用性,即便部分分片不能用,其余分片不会受到影响

 

理想的状况下,有分片就好了,但事实的状况却不大理想。缘由在于,分布式系统中有大量的节点,且经过网络通讯。单个节点的故障(进程crash、断电、磁盘损坏)是个小几率事件,但整个系统的故障率会随节点的增长而指数级增长,网络通讯也可能出现断网、高延迟的状况。在这种必定会出现的“异常”状况下,分布式系统仍是须要继续稳定的对外提供服务,即须要较强的容错性。


最简单的办法,就是冗余或者复制集(Replication),即多个节点负责同一个任务,最为常见的就是分布式存储中,多个节点复杂存储同一份数据,以此加强可用性与可靠性。同时,Replication也会带来性能的提高,好比数据的locality能够减小用户的等待时间。


下面这种来自Distributed systems for fun and profit  的图形象生动说明了Partition与Replication是如何协做的。


  640?wx_fmt=png

Partition和Replication是解决分布式系统问题的一记组合拳,不少具体的问题均可以用这个思路去解决。但这并非银弹,每每是为了解决一个问题,会引入更多的问题,好比为了可用性与可靠性保证,引用了冗余(复制集)。


有了冗余,各个副本间的一致性问题就变得很头疼,一致性在系统的角度和用户的角度又有不一样的等级划分。若是要保证强一致性,那么会影响可用性与性能,在一些应用(好比电商、搜索)是难以接受的。若是是最终一致性,那么就须要处理数据冲突的状况。CAP、FLP这些理论告诉咱们,在分布式系统中,没有最佳的选择,都是须要权衡,作出最合适的选择。



分布式系统挑战


分布式系统须要大量机器协做,面临诸多的挑战:


第一,异构的机器与网络:


分布式系统中的机器,配置不同,其上运行的服务也可能由不一样的语言、架构实现,所以处理能力也不同;节点间经过网络链接,而不一样网络运营商提供的网络的带宽、延时、丢包率又不同。怎么保证你们齐头并进,共同完成目标,这四个不小的挑战。


第二,广泛的节点故障:


虽然单个节点的故障几率较低,但节点数目达到必定规模,出故障的几率就变高了。分布式系统须要保证故障发生的时候,系统仍然是可用的,这就须要监控节点的状态,在节点故障的状况下将该节点负责的计算、存储任务转移到其余节点


第三,不可靠的网络:


节点间经过网络通讯,而网络是不可靠的。可能的网络问题包括:网络分割、延时、丢包、乱序。


相比单机过程调用,网络通讯最让人头疼的是超时:节点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.


刘杰在《分布式系统原理介绍》中指出,处理这些异常的最佳原则是:在设计、推导、验证分布式系统的协议、流程时,最重要的工做之一就是思考在执行流程的每一个步骤时一旦发生各类异常的状况下系统的处理方式及形成的影响。

 


分布式系统特性与衡量标准


透明性:


使用分布式系统的用户并不关心系统是怎么实现的,也不关心读到的数据来自哪一个节点,对用户而言,分布式系统的最高境界是用户根本感知不到这是一个分布式系统,在《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的调度策略很像

  

一致性:


分布式系统为了提升可用性可靠性,通常会引入冗余(复制集)。那么如何保证这些节点上的状态一致,这就是分布式系统不得不面对的一致性问题。一致性有不少等级,一致性越强,对用户越友好,但会制约系统的可用性;一致性等级越低,用户就须要兼容数据不一致的状况,但系统的可用性、并发性很高不少。

 


组件、理论、协议


假设这是一个对外提供服务的大型分布式系统,用户链接到系统,作一些操做,产生一些须要存储的数据,那么在这个过程当中,会遇到哪些组件、理论与协议呢



用一个请求串起来


用户使用Web、APP、SDK,经过HTTP、TCP链接到系统。在分布式系统中,为了高并发、高可用,通常都是多个节点提供相同的服务。那么,第一个问题就是具体选择哪一个节点来提供服务,这个就是负载均衡(load balance)。负载均衡的思想很简单,但使用很是普遍,在分布式系统、大型网站的方方面面都有使用,或者说,只要涉及到多个节点提供同质的服务,就须要负载均衡。

  

经过负载均衡找到一个节点,接下来就是真正处理用户的请求,请求有可能简单,也有可能很复杂。简单的请求,好比读取数据,那么极可能是有缓存的,即分布式缓存,若是缓存没有命中,那么须要去数据库拉取数据。对于复杂的请求,可能会调用到系统中其余的服务。

  

承上,假设服务A须要调用服务B的服务,首先两个节点须要通讯,网络通讯都是创建在TCP/IP协议的基础上,可是,每一个应用都手写socket是一件冗杂、低效的事情,所以须要应用层的封装,所以有了HTTP、FTP等各类应用层协议。当系统越发复杂,提供大量的http接口也是一件困难的事情。所以,有了更进一步的抽象,那就是RPC(remote produce call),是的远程调用就跟本地过程调用同样方便,屏蔽了网络通讯等诸多细节,增长新的接口也更加方便。

  

一个请求可能包含诸多操做,即在服务A上作一些操做,而后在服务B上作另外一些操做。好比简化版的网络购物,在订单服务上发货,在帐户服务上扣款。这两个操做须要保证原子性,要么都成功,要么都不操做。这就涉及到分布式事务的问题,分布式事务是从应用层面保证一致性:某种守恒关系。

  

上面说道一个请求包含多个操做,其实就是涉及到多个服务,分布式系统中有大量的服务,每一个服务又是多个节点组成。那么一个服务怎么找到另外一个服务(的某个节点呢)?通讯是须要地址的,怎么获取这个地址,最简单的办法就是配置文件写死,或者写入到数据库,但这些方法在节点数据巨大、节点动态增删的时候都不大方便,这个时候就须要服务注册与发现:提供服务的节点向一个协调中心注册本身的地址,使用服务的节点去协调中心拉取地址。

  

从上能够看见,协调中心提供了中心化的服务:以一组节点提供相似单点的服务,使用很是普遍,好比命令服务、分布式锁。协调中心最出名的就是chubby,zookeeper。

  

回到用户请求这个点,请求操做会产生一些数据、日志,一般为信息,其余一些系统可能会对这些消息感兴趣,好比个性化推荐、监控等,这里就抽象出了两个概念,消息的生产者与消费者。那么生产者怎么讲消息发送给消费者呢,RPC并非一个很好的选择,由于RPC确定得指定消息发给谁,但实际的状况是生产者并不清楚、也不关心谁会消费这个消息,这个时候消息队列就出马了。简单来讲,生产者只用往消息队列里面发就好了,队列会将消息按主题(topic)分发给关注这个主题的消费者。消息队列起到了异步处理、应用解耦的做用。

  

上面提到,用户操做会产生一些数据,这些数据忠实记录了用户的操做习惯、喜爱,是各行各业最宝贵的财富。好比各类推荐、广告投放、自动识别。这就催生了分布式计算平台,好比Hadoop,Storm等,用来处理这些海量的数据。

  

最后,用户的操做完成以后,用户的数据须要持久化,但数据量很大,大到按个节点没法存储,那么这个时候就须要分布式存储:将数据进行划分放在不一样的节点上,同时,为了防止数据的丢失,每一份数据会保存多分。传统的关系型数据库是单点存储,为了在应用层透明的状况下分库分表,会引用额外的代理层。而对于NoSql,通常自然支持分布式。



一个简化的架构图

  

下面用一个不大精确的架构图,尽可能还原分布式系统的组成部分(不过只能体现出技术,很差体现出理论)


  640?wx_fmt=png

 


概念与实现

  

那么对于上面的各类技术与理论,业界有哪些实现呢,下面进行简单罗列。

  

固然,下面的这些实现,小部分我用过,知其因此然;大部分据说过,知其然;还有一部分以前闻所未闻,分类也不必定正确,只是从其余文章抄过来的。罗列在这里,以便往后或深或浅的学习。

 

  • 负载均衡:
     Nginx:高性能、高并发的web服务器;功能包括负载均衡、反向代理、静态内容缓存、访问控制;工做在应用层
     LVS: Linux virtual server,基于集群技术和Linux操做系统实现一个高性能、高可用的服务器;工做在网络层

  • webserver:
     Java:Tomcat,Apache,Jboss
     Python:gunicorn、uwsgi、twisted、webpy、tornado

  • service:  
     SOA、微服务、spring boot,django

  • 容器:
     docker,kubernetes

  • cache:
     memcache、redis等

  • 协调中心:
     zookeeper、etcd等
     zookeeper使用了Paxos协议Paxos是强一致性,高可用的去中心化分布式。zookeeper的使用场景很是普遍,以后细讲。

  • rpc框架:
     grpc、dubbo、brpc
     dubbo是阿里开源的Java语言开发的高性能RPC框架,在阿里系的诸多架构中,都使用了dubbo + spring boot

  • 消息队列:
     kafka、rabbitMQ、rocketMQ、QSP
     消息队列的应用场景:异步处理、应用解耦、流量削锋和消息通信

  • 实时数据平台:
     storm、akka

  • 离线数据平台:
     hadoop、spark
     PS: apark、akka、kafka都是scala语言写的,看到这个语言仍是很牛逼的

  • dbproxy:
     cobar也是阿里开源的,在阿里系中使用也很是普遍,是关系型数据库的sharding + replica 代理

  • db:
     mysql、oracle、MongoDB、HBase

  • 搜索:
     elasticsearch、solr

  • 日志:
     rsyslog、elk、flume


总结


写完这篇文章,感受本身的回答也很混乱,也没有说清楚,不过对我本身仍是有一些指导意义的,好比,理清了分布式系统中会遇到的各类技术、理论、协议,以及经过一个例子展现他们是如何协做的,接下来就是各个击破了。

  

网上的诸多回答,上来就是看各类论文,google三大件、paxos什么的,我的以为不是很实用。更好的过程,是先有一个总体的把握,而后本身思考会有什么问题,带着问题去寻求答案,在寻求答案的时候再去看论文。

  

另外,也有不少人提到,掌握好计算机基础知识,如操做系统、计算机网络,对学习分布式系统是大有裨益的,这一点我很赞同。分布式系统解决问题的思路是早就有的,不少都是前人研究透的问题,思想都是相同的。好比函数式编程中的map reduce之于Hadoop的MapReduce,好比磁盘存储的raid之于Partition与Replication,好比IPC之于消息队列。


看到这里相信你已经对分布式系统有了基础的概念 剩下的就看各位了!


推荐阅读


技术:jenkins和docker实现自动化构建部署

技术:设计图都不会画,还想作”架构师“?

技术:玩转linux 这些命令就够了 

技术:Kafka、RabbitMQ、RocketMQ等消息中间件的对比

技术:玩转linux 这些命令就够了

技术:30分钟如何学会使用Shiro 


工具:如何经过技术手段 “干掉” 视频APP里讨厌广告?

工具:经过技术手段 “干掉” 视频APP里讨厌的广告之(腾讯视频)


博主11年java开发经验,现从事智能语音工做的研发,关注微信公众号与博主进行技术交流!更过干货资源等你来拿!

640?wx_fmt=jpeg


640?wx_fmt=png