高并发服务端分布式系统设计概要(上)

如何抗大流量高并发?(不要告诉我把服务器买的再好一点)提及来很简单,就是“分”,如何“分”,简单的说就是把不一样的业务分拆到不一样的服务器上去跑(垂直拆分),相同的业务压力分拆到不一样的服务器去跑(水平拆分),并时刻不要忘记备份、扩展、意外处理等讨厌的问题。提及来都比较简单,但设计和实现起来,就会比较困难。之前个人文章,都是“从整到零”的方式来设计一个系统,此次我们就反着顺序来。服务器

        那咱们首先来看,咱们的数据应该如何存储和取用。根据咱们以前肯定的“分”的方法,先肯定如下2点:并发

      (1)咱们的分布式系统,按不一样的业务,存储不一样的数据;(2)一样的业务,同一个数据应存储多份,其中有的存储提供读写,而有的存储只提供读。异步

        好,先解释下这2点。对于(1)应该容易理解,好比说,我这套系统用于微博(就假想咱们作一个山寨的推特吧,给他个命名就叫“山推” 好了,如下都叫山推,Stwi),那么,“我关注的人”这一个业务的数据,确定和“我发了的推文”这个业务的数据是分开存储的,那么咱们如今把,每个业务所负责的数据的存储,称为一个group。即以group的方式,来负责各个业务的数据的存储。接下来讲(2),如今咱们已经知道,数据按业务拆到group里面去存取,那么一个group里面又应该有哪些角色呢?天然的,应该有一台主要的机器,做为group的核心,咱们称它为Group Master,是的,它就是这个group的主要表明。这个group的数据,在Group Master上应该都能找到,进行读写。另外,咱们还须要一些辅助角色,咱们称它们为Group Slaves,这些slave机器作啥工做呢?它们负责去Group Master处拿数据,并尽可能保持和它同步,并提供读服务。请注意个人用词,“尽可能”,稍后将会解释。如今咱们已经有了一个group的基本轮廓:分布式

 

        一个group提供对外的接口(废话不然怎么存取数据),group的底层能够是实际的File System,甚至是HDFS。Group Master和Group Slave能够共享同一个File System(用于不能丢数据的强一致性系统),也能够分别指向不一样的File System(用于弱一致性,容许停写服务和系统宕机时丢数据的系统),但总之应认为这个"File System"是无状态,有状态的是Group Master和各个Group Slave。高并发

        下面来讲一个group如何工做,同步等核心问题。首先,一个group的Group Master和Group Slave
间应保持强一致性仍是弱一致性(最终一致性)应取决于具体的业务需求,以咱们的“山推”来讲,Group Master和Group Slave并不要求保持强一致性,而弱一致性(最终一致性)即能知足要求,为何?由于对于“山推”来说,一个Group Master写了一个数据,而另外一个Group Slave被读到一个“过时”(由于Group Master已经写,但此Group Slave还未更新此数据)的数据一般并不会带来大问题,好比,我在“山推”上发了一个推文,“关注个人人”并无即时同步地看到个人最新推文,并无太大影响,只要“稍后”它们能看到最新的数据便可,这就是所谓的最终一致性。但当Group Master挂掉时,写服务将中断一小段时间由其它Group Slave来顶替,稍后还要再讲这个问题。假如咱们要作的系统不是山推,而是淘宝购物车,支付宝一类的,那么弱一致性(最终一致性)则很难知足要求,同时写服务挂掉也是不能忍受的,对于这样的系统,应保证“强一致性”,保证不能丢失任何数据。性能

        接下来仍是以咱们的“山推“为例,看看一个group如何完成数据同步。假设,如今我有一个请求要写一个数据,因为只有Group Master能写,那么Group Master将接受这个写请求,并加入写的队列,而后Group Master将通知全部Group Slave来更新这个数据,以后这个数据才真正被写入File System。那么如今就有一个问题,是否应等全部Group Slave都更新了这个数据,才算写成功了呢?这里涉及一些NWR的概念,咱们做一个取舍,即至少有一个Group Slave同步成功,才能返回写请求的成功。这是为何呢?由于假如这时候Group Master忽然挂掉了,那么咱们至少能够找到一台Group Slave保持和Group Master彻底同步的数据并顶替它继续工做,剩下的、其它的Group Slave将“异步”地更新这个新数据,很显然,假如如今有多个读请求过来并到达不一样的Group Slave节点,它们极可能读到不同的数据,但最终这些数据会一致,如前所述。咱们作的这种取舍,叫“半同步”模式。那以前所说的强一致性系统应如何工做呢?很显然,必须得等全部Group Slave都同步完成才能返回写成功,这样Group Master挂了,没事,其它Group Slave顶上就行,不会丢失数据,可是付出的代价就是,等待同步的时间。假如咱们的group是跨机房、跨地区分布的,那么等待全部Group Slave同步完成将是很大的性能挑战。因此综合考虑,除了对某些特别的系统,采用“最终一致性”和“半同步”工做的系统,是符合高并发线上应用需求的。并且,还有一个很是重要的缘由,就是一般线上的请求都是读>>写,这也正是“最终一致性”符合的应用场景。spa

        好,继续。刚才咱们曾提到,若是Group Master宕机挂掉,至少能够找到一个和它保持同不的Group Slave来顶替它继续工做,其它的Group Slave则“尽可能”保持和Group Master同步,如前文所述。那么这是如何作到的呢?这里涉及到“分布式选举”的概念,如Paxos协议,经过分布式选举,总能找到一个最接近Group Master的Group Slave,来顶替它,从而保证系统的可持续工做。固然,在此过程当中,对于最终一致性系统,仍然会有一小段时间的写服务中断。如今继续假设,咱们的“山推”已经有了一些规模,而负责“山推”推文的这个group也有了五台机器,并跨机房,跨地区分布,按照上述设计,不管哪一个机房断电或机器故障,都不会影响这个group的正常工做,只是会有一些小的影响而已。设计

        那么对于这个group,还剩2个问题,一是如何知道Group Master挂掉了呢?二是在图中咱们已经看到Group Slave是可扩展的,那么新加入的Group Slave应如何去“偷”数据从而逐渐和其它节点同步呢?对于问题一,咱们的方案是这样的,另外提供一个相似“心跳”的服务(由谁提供呢,后面咱们将讲到的Global Master将派上用场),group内全部节点不管是Group Master仍是Group Slave都不停地向这个“心跳”服务去申请一个证书,或认为是一把锁,而且这个锁是有时间的,会过时。“心跳”服务按期检查Group Master的锁和其有效性,一旦过时,若是Group Master工做正常,它将锁延期并继续工做,不然说明Group Master挂掉,由其它Group Slave竞争获得此锁(分布式选举),从而变成新的Group Master。对于问题二,则很简单,新加入的Group Slave不断地“偷”老数据,而新数据总因为Group Master通知其更新,最终与其它全部结点同步。(固然,“偷”数据所用的时间并不乐观,一般在小时级别)orm

相关文章
相关标签/搜索