分布式架构的演进过程

一、计算机的基石——冯诺依曼模型

       冯·诺依曼于1946年提出存储程序原理,把程序本身当作数据来对待,程序和该程序处理的数据用同样的方式储存。 冯·诺依曼体系结构冯·诺依曼理论的要点是:计算机的数制采用二进制;计算机应该按照程序顺序执行。人们把冯·诺依曼的这个理论称为冯·诺依曼体系结构。

       

      直到现在我们的计算机都属于这个体系结构,只不过性能大大提升。

二、bigger than bigger——计算机的产生 大型主机时代

        世界上第一台通用计算机“ENIAC”于1946年在美国宾夕法尼亚大学诞生。发明人是美国人莫克利(JohnW.Mauchly)和艾克特(J.PresperEckert)。美国国防部用它来进行弹道计算。它是一个庞然大物,用了18000个电子管,占地170平方米,重达30吨,耗电功率约150千瓦,每秒钟可进行5000次运算。
        ENIAC之后,电子计算机进入了由IBM这位蓝色巨人主导的大型机时代。

        大型机之父 吉恩 阿姆达尔在1964年4月7日,制造出第一台IBM大型机SYSTEM/360,使得IBM在20世纪50-60年代统治整个大型计算机工业。

        

       由于大型机高可靠性和超强的计算能力,即使在X86架构和云计算飞速发展的情况下,IBM大型机仍然牢牢占据着一定的高端市场份额。

       在20世纪80年代时,计算机架构同时向两个方向发展:

     (1) 以CISC(微处理器执行的计算机语言指令集)CPU为架构 价格比较便宜 面向个人的计算机(PC)

     (2)以RISC(精简指令集计算机)CPU为架构 架构昂贵 面向企业的小型UNIX 服务器

      之后,虽然大型主机具备超强的计算和I/O处理能力,并且拥有很好的稳定性和安全性。

      但是,这种架构日益难以适应人们的需求:

     (1)大型机的复杂性,使得其运维人员的培养成本很高

     (2)大型机很贵,一般人或者企业根本玩不起,基本上只有政府或者大型国企才能弄一台

     (3)单点问题  一台大型主机故障,则整个系统瘫痪

     (4)PC的性能不断提升,许多企业完全不必要再使用大型机来搭建系统架构

三、分布式的意义和常见概念

分布式系统的意义

1、升级单机处理性能的性价比越来越低

单机处理能力主要依靠CPU、内存和磁盘,通过更换硬件做垂直扩展来提升性能的代价越来越高

2、单机处理能力存在瓶颈

3、单机系统存在稳定性和可用性问题

下面以饭店为例,来解释常见概念

集群

       从前有一个小饭店,客少店小,因此只有一个厨师,而且除了炒菜,洗菜切菜也得自己来,然后客人逐渐多了起来,这时候就多招了两个厨师,这个厨师也是炒菜洗菜切菜什么都干,这三个厨师的关系,就叫做集群。

                       

分布式

        小饭店生意越来越好了,为了增加效率,专人干专事,给每一位厨师配一个配菜员一个切菜员,这个时候厨师和配菜师 切菜员是分布式的关系,而配菜师与配菜师之间的关系还是集群

        在这个过程中,一个配菜师因故请假了,但是其余的配菜师还是该啥就干啥,可能没请假的配菜师任务会被均匀的加量了,但是他们的任务和职责是不变的

        

节点

       节点是指一个可以独立按照分布式完成一组逻辑的程序个体。在具体的项目中,一个节点表示的是一个操作系统上的进程。

副本机制

       副本(replica/copy)指在分布式系统中为数据或服务提供的冗余。

       数据副本指在不同的节点上持久化同一份数据,当出现某一个节点的数据丢失时,可以从副本上读取到数据。数据副本是分布式系统中解决数据丢失问题的唯一手段。

       服务副本表示多个节点提供相同的服务,通过主从关系来实现服务的高可用方案

中间件

       中间件位于操作系统提供的服务之外,又不属于应用,他是位于应用和系统层之间为开发者方便的处理通信,输入输出的一类软件,能够让用户关心自己应用的部分。

即:分布式:一个业务拆分为多个子业务,部署在不同的服务器上

           集群:同一个业务,部署在多个服务器上

       分布式结构:将一个完整的系统,按照业务功能,拆分成一个个独立的子系统,在分布式结构中,每个子系统就被称为"服务"。这些子系统能够独立运行在web容器中,他们之间通过RPC方式通信。

      

下面我们将电商系统为例,详细介绍分布式发展过程

 假设我们的电商系统中只有三个模块:用户模块,交易模块和商品模块

 阶段一:单应用架构

 在网站创建初期,经常把所有的东西都在一台机器上部署,这个时候的架构是单应用架构,优点是效率非常高

阶段二:应用服务器和数据库服务器分离

网站上线了,随着时间推移,访问量开始逐渐增大,服务器逐渐的就扛不住了,这个时候就要考虑加机器了,这就进入了第二阶段。

这个阶段增加机器的主要目的是将web服务器和数据库服务器进行拆分,这样不仅提高了单机的负载能力,也提高了容灾能力

第三阶段:应用服务器集群

然而随着访问量的持续增加,单台服务器已经无法满足需求。假设数据库服务器的还未遇到性能问题

此时可以增加应用服务器,这就进入第三阶段——应用服务器集群。

在这个阶段有些问题就逐渐显现出来了,比如:

(1)用户的请求该由哪一台机器进行处理? ——负载均衡(F5/apache/nginx)

(2)如果用户每次请求的机器不同,那么session如何维护?

1、session同步

   

2、通过第三方存储(redis等)存储session

3、跳过容器对象

这样架构就变为了以下模式。

阶段四:数据库读写分离

随着业务量进一步增加,数据库服务器的I/O能力会存在瓶颈。

首先考虑的是加机器,但是如果直接一分为二,每次读写还要额外判断数据应该在哪台机器上。

基于电商系统数据库读多写少的特点,可以将一个服务器作为写库,另一个库设为读库,并设置主从同步进行复制。

这样也会带来数据库不一致的问题

1.主从数据库之间的数据同步;可以使用mysql自带的master-slave方式实现主从复制

2.对应数据源的选择;采用第三方数据库中间件,例如mycat

实际上,如果读库的量远大于写库的访问量,需要设置多个读库时,可以采取以下的结构

阶段五:使用搜索引擎缓解读库的压力

       数据库做读库的话,常常对模糊查询效率不是特别好,像电商类的网站,搜索是非常核心的功能,即便是做了读写分离,这个问题也不能有效的解决。那么这个时候就需要引入搜索引擎了。

       使用搜索引擎能够大大提高我们的查询速度,但是同时也会带来一些附加的问题,比如维护索引构建。

       

阶段六:引入缓存机制 

随着访问量的持续增加,逐渐出现许多用户访问统一部分内容的情况,对于这些热点数据,没必要每次都从数据库去读取,我们可以使用缓存技术,比如memcache,redis来作为我们应用层的缓存;另外在某写场景下,比如我们对用户的某些IP的访问频率做限制,那这个放内存中又不合适,放数据库又太麻烦,这个时候可以使用Nosql的方式比如mongDB来代替传统的关系型数据库。

至此,分布式架构的基本框架已经形成。

阶段七:数据库的水平、垂直拆分

数据库永远是最容易造成瓶颈的地方之一,例如阿里巴巴09年“去IOE运动”就是为了解决数据库扩展性瓶颈问题。

在整个架构的编号过程中,所有的数据还是在同一个数据库中的,因此我们可以考虑对数据进行拆分

其中:

垂直拆分就是把不同业务的数据拆分到不同的数据库中

水平拆分则是把同一个表中的数据拆分到两个甚至更多的数据库中,有些公司的数据库是按照日期分为31*N个数据库

阶段八:应用拆分阶段

       随着业务的发展,业务越来越多,应用的压力越来越大。工程规模也越来越庞大。这个时候就可以考虑讲应用拆分,按照领域模型讲我们的用户,商品,交易拆分成多个子系统

这样拆分以后,可能会有一些相同的代码,比如用户操作,在商品和交易都需要查询,所以会导致每个系统都会有用户查询访问相关操作。这些相同的操作一定是要抽象出来,否则就会是个坑。所以通过走服务化路线的方式来解决。

那么服务拆分以后,各个服务之间如何进行远程通信呢?

通过RPC技术,比较典型的有:webservice,hession,http,RMI等等

前期通过这些技术能够很好的解决各个服务器之间通信问题,but,互联网的发展是持续的,所以架构的演变和优化还在持续。

总结梳理

分布式系统的难点

       毫无疑问,分布式系统对于集中式系统而言,在实现上会更加复杂。分布式系统将会是更难理解,设计,构建和管理的,同时意味这应用程序的根源问题更难发现。

三态

         在集中式架构中,我们调用一个接口返回的结果只有两种,成功或失败,但是在分布式领域中,会出现"超时"这个状态。

 分布式事务

       这是一个老生常谈的问题,我们都知道事务就是一些列操作的原子性保证,在单机的情况下,我们能够依靠本机的数据库连接和组件轻易做到事务控制,但是分布式情况下,业务原子性操作很可能是跨服务的,这样就导致了分布式事务,例如A和B操作分别是不同服务下的同一个事务操作内的操作,A调用B,A如果可以清楚的知道B是否成功提交从而控制自身的提交还是回滚操作,但是在分布式系统中调用会出现一个新状态就是超时,就是A无法知道B是成功还是失败,这个时候A是提交本地事务还是回滚呢?其实这是一个很难的问题,如果强行保证事务一致性,可以采取分布式锁,但是那样会增加系统复杂度而且会增大系统开销,而且事务跨域的服务越多,消耗的资源越大,性能越低,所以最好的解决方案就是避免分布式事务。

       还有一种解决方案就是重试机制,但是重试机制如果不是查询接口,必须涉及到数据库的变更,如果第一次调用成功但是没有返回成功结果,那调用方第二次调用对调用方来说依然是重试,但是对于被调用方来说是重复调用,例如A向B转账,A-100,B+100,这样会导致A扣了100,而B增加200。这样的结果不是我们期待的,因此需在要写入的接口做幂等设计。多次调用和单次调用是一样的效果。通常可以设置一个唯一键,在写入的时候查询是否已经存在,避免重复写入。但是幂等设计的一个前提就是服务是高可用,否则无论怎么重试都不能调用返回一个明确的结果调用方会一直等待,虽然可以限制重试的次数,但是这已经进入了一个异常状态了,甚至到了极端情况还是需要人肉补偿处理。其实根据CAP和BASE理论,不可能在高可用分布式情况下做到一致性,一般都是最终一致性保证。

负载均衡

        每个服务单独部署,为了达到高可用,每个服务至少是两台机器,因为互联网公司一般使用可靠性不是特别高的普通机器,长期运行宕机概率很高,所以两台机器能够大大降低服务不可用的可能性,这正是大型项目会采用十几台甚至上百台来部署一个服务,这不仅是保证服务的高可用,更是提升服务的QPS,但是这样又带来一个问题,一个请求过来到底路由到哪台机器?路由算法很多,又DNS路由,如果session在本机,还会根据用户id或者cookie等信息路由到固定的机器,当然现在应用服务器为了扩展的方便都会设计为无状态的,session会保存到专有的session服务器,所有不会涉及到拿不到session问题。那路由规则是随机获取么?这是一个方法,但是据我所知,实际情况肯定比这个复杂,在一定范围内随机,但是在大的范围也会分为很多个域,例如如果为了保证异地多活的多机房,跨机房调用的开销太大,肯定会优先选择同机房的服务,这个要参考具体的机器分布来考虑。

一致性

       数据被分散或者复制到不同的机器上,如何保证各台主机之间的数据的一致性将成为一个难点。

故障独立性

       分布式系统由多个节点组成,整个分布式系统完全出问题的概率是存在的,但是在时间中出现更多的是某个节点出问题,其他节点都没问题。这种情况下我们实现分布式系统时需要考虑更加全面写。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值