高并发服务端分布式系统设计概要(下)html
上篇 连接地址:http://www.cnblogs.com/ccdev/p/3338412.html算法
中篇 连接地址:http://www.cnblogs.com/ccdev/p/3340484.html浏览器
如今接着设计咱们的“山推”系统。有了前面两篇的铺垫,咱们的系统如今已经有了五脏六腑,剩下的工做就是要让其羽翼丰满。那么,是时候,放出咱们的“山推”系统全貌了:缓存
前面啰嗦了半天,也许很多同窗看的不明不白,好了,如今开始看图说话环节:服务器
(1)整个系统由N台机器组合而成,其中Global Master一台,Global Slave一台到多台,二者之间保持强一致性并彻底同步,可由Global Slave随时顶替Global Master工做,它们被Global Heartbeat(一台)来管理,保证有一个Global Master正常工做;Global Heartbeat因为无压力,一般认为其不能挂掉,若是它挂掉了,则必须人工干预才能恢复正常;并发
(2)整个系统由多个groups合成,每个group负责相应业务的数据的存取,它们是数据节点,是真正抗压力的地方,每个group由一个Group Master和一个到多个Group Slave构成,Group Master做为该group的主节点,提供读和写,而Group Slave则只提供读服务且保证这些Group Slave节点中,至少有一个和Group Master保持彻底同步,剩余的Group Slave和Group Master可以达到最终一致,它们之间以“半同步”模式工做保证最终一致性;负载均衡
(3)每个group的健康状态由Global Master来管理,Global Master向group发送管理信息,并保证有一个Group Master正常工做,若Group Master宕机,在该group内经过分布式选举产生新的Group Master顶替原来宕机的机器继续工做,但仍然有一小段时间须要中断写服务来切换新的Group Master;分布式
(4)每个group的底层是实际的存储系统,File system,它们是无状态的,即,由分布式选举产生的Group Master能够在原来的File system上继续工做;高并发
(5)Client的上端可认为是Web请求,Client在“首次”进行数据读写时,向Global Master查询相应的group信息,并将其缓存,后续将直接与相应的group进行通讯;为避免大量“首次”查询冲垮Global Master,在Client与Global Master之间增长DNS负载均衡,可由Global Slave分担部分查询工做;性能
(6)当Client已经拥有足够的group信息时,它将直接与group通讯进行工做,从而真正的压力和流量由各个group分担,并处理完成须要的工做。
好了,如今咱们的“山推”系统设计完成了,可是要将它编码实现,还有很远的路要走,细枝末节的问题也会暴露更多。若是该系统用于线上计算,若有大量的Map-Reduce运行于group中,系统将会更复杂,由于此时不光考虑的数据的存储同步问题,操做也须要同步。如今来检验下咱们设计的“山推”系统,主要分布式指标:
一致性:如前文所述,Global机器强一致性,Group机器最终一致性;
可用性:Global机器保证了HA(高可用性),Group机器则不保证,但知足了分区容错性;
备份Replication:Global机器采用彻底同步,Group机器则是半同步模式,均可以进行横向扩展;
故障恢复:如前文所述,Global机器彻底同步,故障可不受中断由slave恢复工做,但Group机器采用分布式选举和最终一致性,故障时有较短期的写服务须要中断并切换到slave机器,但读服务可不中断。
还有其余一些指标,这里就再也不多说了。还有一些细节,须要提一下,好比以前的评论中有同窗提到,group中master挂时,由slave去顶替,但这样一来该group内其余全部slave须要分担以前成这新master的这个slave的压力,有可能继续挂掉而形成雪崩。针对此种状况,可采用以下作法:即在一个group内,至少还存在一个真正作“备份”用途的slave,平时不抗压力,只同步数据,这样当出现上述状况时,可由该备份slave来顶替成为新master的那个slave,从而避免雪崩效应。不过这样一来,就有新的问题,因为备份slave平时不抗压力,加入抗压力后必然产生必定的数据迁移,数据迁移也是一个较麻烦的问题。常采用的分摊压力作法如一致性Hash算法(环状Hash),可将新结点加入对整个group的影响降到较小的程度。
另外,还有一个较为棘手的问题,就是系统的日志处理,主要是系统宕机后如何恢复以前的操做日志。比较常见的方法是对日志做快照(Snapshot)和回放点(checkpoint),并采用Copy-on-write方式按期将日志做snapshot存储,当发现宕机后,找出对应的回放点并恢复以后的snapshot,但此时仍可能有新的写操做到达,并产生不一致,这里主要依靠Copy-on-write来同步。
最后再说说图中的Client部分。显然这个模块就是面向Web的接口,后面链接咱们的“山推”系统,它能够包含诸多业务逻辑,最重要的,是要缓存group的信息。在Client和Web之间,还能够有诸如Nginx之类的反向代理服务器存在,作进一步性能提高,这已经超出了本文的范畴,但咱们必须明白的是,一个高并发高性能的网站,对性能的要求是从起点开始的,何为起点,即用户的浏览器。
如今,让咱们来看看GFS的设计:
很明显,这么牛的系统我是设计不出来的,咱们的“山推”,就是在学习GFS + Bigtable的主要思想。说到这,也必须提一句,可能我文章中,名词摆的有点多了,如NWR,分布式选举,Paxos包括Copy-on-write等,有兴趣的同窗可自行google了解。由于说实在的,这些概念我也无法讲透彻,只是只知其一;不知其二。另外,你们可参考一些分布式项目的设计,如Cassandra,包括淘宝的Oceanbase等,以加深理解。
就写到这里算是完结了。因为写的比较匆忙,可能包含一些错误,但愿同窗们不吝赐教!提早祝你们国庆节快乐。