基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋


当前第2页 返回上一页

数据流入整个系统中,在系统中不管是做计算还是存储,这些经过处理的数据如果需要发挥作用,都要流入到下游系统中,所以“导出数据”这个过程起到的是一个连接上下游,承上启下的作用。图 14 是这个系统的总架构图,因为当时并未对导出服务做细粒度的任务切分,并且单台server也处理不了过大的用户任务,所以在高峰期时,会导致延迟增大,基于此,我们经过一个月的开发最终推出了一个全新的版本。

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 15

如图 15 所示,是经过改进后的整体架构图。图的顶层是我们的master,用它来控制所有任务的调度管理。所有任务都是经由调度器转发给master,由master来评估每一台机器上的负载,之后再根据机器本身的一些状态(CPU使用率、网络带宽、执行任务的情况)去做相应的调度,除此之外我们还将任务做了更细粒度的切分。

调度方法的设计首要考虑到的就是面向资源,其次需要充分利用异构机器,并且能满足自动调整。面向资源大家都能够理解,充分利用异构的机器,是因为我们机器规格众多,所能解决的任务强度不一致,我们需要充分利用该机器的资源,而不能让其在处理任务时,有"机器资源"不足或浪费的情况发生;至于自动调整,就是可以保证在面对用户量突增或者突减这种突发情况发生时,我们具备自动调整任务分布的能力,其最终的目的也是为了充分利用资源。

* 任务分配

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 16

图 16 是任务分配的过程图。假设最初任务(T1-T7)都相对均匀的分布在三台机器上,此时又有另外两个任务(T8-T9)进入,那么我们就需要寻找一些相对比较空闲的机器(S1 或 S2)优先将这两个任务分配给他们。这只是针对一个相对比较均衡的情况做的一个调整。

* 自动调整

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 17

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 18

当然也会有不均衡的情况产生(图 17-18)那么此时就需要我们去做一些自动调整,比如有一个用户删除了其很多任务,那么此时的S1与S2相对S3会比较空闲,那么此时我们就需要通过server向master上报心跳,这个内容包括对资源的占用以及任务的分布情况,根据结果对比较空闲的机器做一个调整,保持一个相对平衡的状态。

* 水平扩展

图 19

图 19 是进行水平扩展时会产生的一个问题。所有机器目前都处于一个比较繁忙的状态,此时如果过来一个新的任务(T13),但是前12个任务已经全部分布在这三台机器上面处理,腾不出空闲的机器处理新增任务,那么此时就会需要对机器进行扩容。

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 20

如图 20 所示,在前三台机器都处于“忙碌”状态时,我们需要新增server4,一旦启动S4,它会向master汇报心跳,然后master就会感知到这个任务的存在以及S4的存在,重新对整个资源分布使用情况做一次评估,将T13分配到比较空闲的S4上,甚至可以将在S1、S2、S3等待处理的任务分配到S4上。

  • 资源隔基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 21

实际上,不单单是对任务进行自动调整均衡分担机器处理压力是非常重要的,对于一些比较特殊的任务,如何保证这个用户流量在突增时不会影响到其他相对较小的用户,或是当数据导出到云存储进行压缩时(压缩的过程非常耗费CPU资源)如何保证它不会影响其他任务,这些都是我们需要处理的问题。针对这些问题我们提出了资源隔离的概念(图 21)将机器和任务进行隔离,提供调度组(调度组中是相近的一组机器或者是一类任务)功能,通过对他们物理上的隔离,达到相互之间互不影响,并对资源进行充分利用。

* master高可用

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 22

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 23

综上我们可以看出我们的系统是一对多的状态(一个master对多个server)那么在这种情况下,如何解决在出现单点故障时仍然保证服务的高可用。如图22到图23所示,是我们设计的一个核心所在,我们可以在图中看到最底端是一个zookeeper集群,我们通过对一个临时文件的创建来模拟一个锁,多台机器可以同时去抢占这把锁,抢占成功的master会成为一个主master,没有抢占成功的则会作为一个备份,在平时会空闲,但一旦S1丢锁,master2就会抢占锁,接过整个调度任务以及一些集群管理任务,这就是master高可用思路。

* Server高可用

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 24

server高可用,我们也是采用类似的思路。我们将master视作一个高可用节点,每一个server都需要向master汇报心跳,心跳的内容包含了机器本身的存活以及相应任务的执行情况。如图 24 所示,master一旦感知到S3宕机,那么此时就会将S3上执行的两个任务(T5-T6)都调走,并且它会认为S1与S2是相对比较合适的选择,并且会将这两个任务调去相应的server上,这样就完成了server的高可用目标。

* 系统级水平扩展

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 25

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 26

最开始有提及我们的整个消息队列是使用kafka实现的,kafka其实也是有上限的,在最开始我们也是采用了kafka单个集群(图 25)后来发现,一旦业务量上来,消息队列数据一旦多到一定程度,系统会发生雪崩。所以我们对单个集群做了一个扩展(图 26)将单个kafka集群直接拆成多个集群,让每一个kafka集群都保持一个相对比较小的规模,这样性能方面就会得到很大的提升,图 26 所示就是经过扩展后的情况,由三个kafka提供的信息会汇总到我们的调度器上,调度器通过压力或者是消息队列的数量,对用户新创建的任务以及新的数据源进行分配,分配至合适的kafka集群中。

上下游协议优化

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 27

在实践中还是会出现上下游之间性能较低的情况。在最开始,我们采用Json来做上下游的数据传输,可是在日志检索时暴露出的问题就是,这样做对网络消耗很大,于是我们决定采用Protobuf进行上下游数据传输。图 27 展示了使用Json与Protobuf时,从序列化、反序列化角度进行对比的数据结果展示,从图中可以看出,使用Protobuf消耗的时间都更短,尤其在反序列化时,它的CPU消耗降低了将近一个数量级。因此,采用这种方式,不管从集群计算资源利用还是从网络带宽提升上都将效率提升了数倍。

* 流水线处理

基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

图 28

至于对流水线的处理,最开始的设计其实是一个串行的操作,导出服务从消息队列当中拉取数据,经过处理之后做一个推送,持续这样的工作过程,其中处理操作是很快的,但是拉取和推送相对就很慢,这样的一个过程,执行效率其实是很低的,并且由于每种操作的处理时间不一样,有的快有的慢,就导致在监控图上监察到网络的趋势图是时高时低的,也就导致了利用率的降低。鉴于此,我们优化了流水线操作,采用并行化操作(图 28)结果显示,这样做的结果是推送和拉取效率都会比上面一种方式高。

Golang GC

我们的整个语言选型是采用Golang的,而它是一个带GC的语言,实际上出现的情况还是很多的,系统当中会有1/10的时间是不干活而在进行垃圾回收的。因此在代码层面我们做了一些改进,一个是sync.Pool的使用能够降低垃圾回收的频率;其次是重用对象,将一个对象尽可能重复使用,这样一来,每一次GC的量就会减小。之后我们对Golang进行了版本升级,升级至1.8版本后我们再查看了一下GC的耗时,发现提升了将近两个数量级。这就是代码层面的优化。

有限资源假设

最后叙述一下我们关于资源假设方面进行的一个优化,也就是要建立起一个有限资源假设的概念。前段时间由于数据接入量比较大,我们需要自己进行运维,突发接入的客户,会使系统轻易就被跑满,此时我们会想办法加机器或者是说在调度上去做一些调整和优化,但是这样终究不是一个长久的办法。于是我们会在刚开始去做一个资源有限假设,就是要在最开始评估出来资源有限情况下我们该如何去做。比如需要提前预估出10M带宽所能对应多少用户的任务,这个必须是有一个数据存在的,并且在这个基础上我们需要做一个资源的预估和集群资源的规划。根据这个预估的数据的情况,去划定一个水位标准,超过水位标准之后,再考虑是不是需要进行扩容。客户这边也需要沟通清楚我们现有的处理能力,这样,才能保证整个集群/服务是处于一个比较健康的状态。

成果

上面我们提及了我们的架构实现以及整体的一个优化,目前的成果就是:我们支撑了万亿级的数据点,并且每天可以处理几百TB的数据,以及支持海量用户。我们的系统目前保持很低的延迟,较高的处理效率;由于我们实现了自动化运维,所以人力成本也大大减少,我们的期望就是可以在写代码时不被运维事情干扰;至于可用性,目前已经达到3个9(99.9%)的成效。

以上就是我今天分享的全部内容。


本文来自:51CTO博客

感谢作者:mob604756f0bbf4

查看原文:基于Go语言构建的万亿级流量大数据平台架构|文末彩蛋

返回前面的内容

相关阅读 >>

Golang escape analyze

Golang和erlang区别

手撸Golang 仿spring ioc/aop 之9 扫码4

【paspberry pi】部署kubernetes

Golang怎么判断map是否为空

Go语言学习10-指针类型

mysql explain

手撸Golang 仿spring ioc/aop 之4 蓝图

Go基础及语法(一)

聊聊dubbo-Go-proxy的apifilter

更多相关阅读请进入《Go》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...