常用的几种大数据架构剖析

数据分析工作虽然隐藏在业务系统背后,但是具有非常重要的作用,数据分析的结果对决策、业务发展有着举足轻重的作用。随着大数据技术的发展,数据挖掘、数据探索等专有名词曝光度越来越高,但是在类似于Hadoop系列的大数据分析系统大行其道之前,数据分析工作已经经历了长足的发展,尤其是以BI系统为主的数据分析,已经有了非常成熟和稳定的技术方案和生态系统,对于BI系统来说,大概的架构图如下:

可以看到在BI系统里面,核心的模块是Cube,Cube是一个更高层的业务模型抽象,在Cube之上可以进行多种操作,例如上钻、下钻、切片等操作。大部分BI系统都基于关系型数据库,关系型数据库使用SQL语句进行操作,但是SQL在多维操作和分析的表示能力上相对较弱,所以Cube有自己独有的查询语言MDX,MDX表达式具有更强的多维表现能力,所以以Cube为核心的分析系统基本占据着数据统计分析的半壁江山,大多数的数据库服务厂商直接提供了BI套装软件服务,轻易便可搭建出一套Olap分析系统。不过BI的问题也随着时间的推移逐渐显露出来:

  • BI系统更多的以分析业务数据产生的密度高、价值高的结构化数据为主,对于非结构化和半结构化数据的处理非常乏力,例如图片,文本,音频的存储,分析。
  • 由于数据仓库为结构化存储,在数据从其他系统进入数据仓库这个东西,我们通常叫做ETL过程,ETL动作和业务进行了强绑定,通常需要一个专门的ETL团队去和业务做衔接,决定如何进行数据的清洗和转换。
  • 随着异构数据源的增加,例如如果存在视频,文本,图片等数据源,要解析数据内容进入数据仓库,则需要非常复杂等ETL程序,从而导致ETL变得过于庞大和臃肿。
  • 当数据量过大的时候,性能会成为瓶颈,在TB/PB级别的数据量上表现出明显的吃力。
  • 数据库的范式等约束规则,着力于解决数据冗余的问题,是为了保障数据的一致性,但是对于数据仓库来说,我们并不需要对数据做修改和一致性的保障,原则上来说数据仓库的原始数据都是只读的,所以这些约束反而会成为影响性能的因素。
  • ETL动作对数据的预先假设和处理,导致机器学习部分获取到的数据为假设后的数据,因此效果不理想。例如如果需要使用数据仓库进行异常数据的挖掘,则在数据入库经过ETL的时候就需要明确定义需要提取的特征数据,否则无法结构化入库,然而大多数情况是需要基于异构数据才能提取出特征。

在一系列的问题下,以Hadoop体系为首的大数据分析平台逐渐表现出优异性,围绕Hadoop体系的生态圈也不断的变大,对于Hadoop系统来说,从根本上解决了传统数据仓库的瓶颈的问题,但是也带来一系列的问题:

  1. 从数据仓库升级到大数据架构,是不具备平滑演进的,基本等于推翻重做。
  2. 大数据下的分布式存储强调数据的只读性质,所以类似于Hive,HDFS这些存储方式都不支持update,HDFS的write操作也不支持并行,这些特性导致其具有一定的局限性。

基于大数据架构的数据分析平台侧重于从以下几个维度去解决传统数据仓库做数据分析面临的瓶颈:

  1. 分布式计算:分布式计算的思路是让多个节点并行计算,并且强调数据本地性,尽可能的减少数据的传输,例如Spark通过RDD的形式来表现数据的计算逻辑,可以在RDD上做一系列的优化,来减少数据的传输。
  2. 分布式存储:所谓的分布式存储,指的是将一个大文件拆成N份,每一份独立的放到一台机器上,这里就涉及到文件的副本,分片,以及管理等操作,分布式存储主要优化的动作都在这一块。
  3. 检索和存储的结合:在早期的大数据组件中,存储和计算相对比较单一,但是目前更多的方向是在存储上做更多的手脚,让查询和计算更加高效,对于计算来说高效不外乎就是查找数据快,读取数据快,所以目前的存储不单单的存储数据内容,同时会添加很多元信息,例如索引信息。像类似于parquet和carbondata都是这样的思想。

总的来说,目前围绕Hadoop体系的大数据架构大概有以下几种:

传统大数据架构

​之所以叫传统大数据架构,是因为其定位是为了解决传统BI的问题,简单来说,数据分析的业务没有发生任何变化,但是因为数据量、性能等问题导致系统无法正常使用,需要进行升级改造,那么此类架构便是为了解决这个问题。可以看到,其依然保留了ETL的动作,将数据经过ETL动作进入数据存储。

优点:简单,易懂,对于BI系统来说,基本思想没有发生变化,变化的仅仅是技术选型,用大数据架构替换掉BI的组件。

缺点:对于大数据来说,没有BI下如此完备的Cube架构,虽然目前有kylin,但是kylin的局限性非常明显,远远没有BI下的Cube的灵活度和稳定度,因此对业务支撑的灵活度不够,所以对于存在大量报表,或者复杂的钻取的场景,需要太多的手工定制化,同时该架构依旧以批处理为主,缺乏实时的支撑。

适用场景:数据分析需求依旧以BI场景为主,但是因为数据量、性能等问题无法满足日常使用。

流式架构

在传统大数据架构的基础上,流式架构非常激进,直接拔掉了批处理,数据全程以流的形式处理,所以在数据接入端没有了ETL,转而替换为数据通道。经过流处理加工后的数据,以消息的形式直接推送给了消费者。虽然有一个存储部分,但是该存储更多的以窗口的形式进行存储,所以该存储并非发生在数据湖,而是在外围系统。

优点:没有臃肿的ETL过程,数据的实效性非常高。

缺点:对于流式架构来说,不存在批处理,因此对于数据的重播和历史统计无法很好的支撑。对于离线分析仅仅支撑窗口之内的分析。

适用场景:预警,监控,对数据有有效期要求的情况。

Lambda架构

Lambda架构算是大数据系统里面举足轻重的架构,大多数架构基本都是Lambda架构或者基于其变种的架构。Lambda的数据通道分为两条分支:实时流和离线。实时流依照流式架构,保障了其实时性,而离线则以批处理方式为主,保障了最终一致性。什么意思呢?流式通道处理为保障实效性更多的以增量计算为主辅助参考,而批处理层则对数据进行全量运算,保障其最终的一致性,因此Lambda最外层有一个实时层和离线层合并的动作,此动作是Lambda里非常重要的一个动作,大概的合并思路如下:

优点:既有实时又有离线,对于数据分析场景涵盖的非常到位。

缺点:离线层和实时流虽然面临的场景不相同,但是其内部处理的逻辑却是相同,因此有大量冗余和重复的模块存在。

适用场景:同时存在实时和离线需求的情况。

Kappa架构

​ Kappa架构在Lambda 的基础上进行了优化,将实时和流部分进行了合并,将数据通道以消息队列进行替代。因此对于Kappa架构来说,依旧以流处理为主,但是数据却在数据湖层面进行了存储,当需要进行离线分析或者再次计算的时候,则将数据湖的数据再次经过消息队列重播一次则可。

优点:Kappa架构解决了Lambda架构里面的冗余部分,以数据可重播的超凡脱俗的思想进行了设计,整个架构非常简洁。

缺点:虽然Kappa架构看起来简洁,但是施难度相对较高,尤其是对于数据重播部分。

适用场景:和Lambda类似,改架构是针对Lambda的优化。

Unified架构

​ 以上的种种架构都围绕海量数据处理为主,Unifield架构则更激进,将机器学习和数据处理揉为一体,从核心上来说,Unifield依旧以Lambda为主,不过对其进行了改造,在流处理层新增了机器学习层。可以看到数据在经过数据通道进入数据湖后,新增了模型训练部分,并且将其在流式层进行使用。同时流式层不单使用模型,也包含着对模型的持续训练。

优点:Unifield架构提供了一套数据分析和机器学习结合的架构方案,非常好的解决了机器学习如何与数据平台进行结合的问题。

缺点:Unifield架构实施复杂度更高,对于机器学习架构来说,从软件包到硬件部署都和数据分析平台有着非常大的差别,因此在实施过程中的难度系数更高。

适用场景:有着大量数据需要分析,同时对机器学习方便又有着非常大的需求或者有规划。

总结

以上几种架构为目前数据处理领域使用比较多的几种架构,当然还有非常多其他架构,不过其思想都会或多或少的类似。数据领域和机器学习领域会持续发展,以上几种思想或许终究也会变得过时。


更多精彩洞见,请关注微信公众号:思特沃克

Share

从分布式计算到分布式训练

对计算机来讲,所谓的计算,不过是将存储在各个地方的数据通过数据总线进行传输,然后经过算术逻辑单元执行一系列预设好的规则,最终再将输出写入到某个位置。

在计算能力有限、存储成本偏高的情况下,就需要利用好计算机的资源,让它的计算能力发挥出最大的价值,所以在编程初期用指令直接操作硬件,例如汇编语言中常见的操纵寄存器,本质上都是为了减少数据传输的时间,充分利用CPU的计算能力,避免因为数据的长时间传输导致CPU进行过长的等待。

分布式计算的到来

随着科技的发展,“数据存储”领域有了质和量的双向发展,除了稳定性、安全性的提升外,容量也呈指数级增长。因此可以在单机上直接构建整套服务,类似LAMP类似的这种一键搭建服务器的套装软件有了更多的应用场景。

然而随着业务的发展,另一个问题逐渐显现出来:虽然磁盘容量增加了,但是机器的访问速度并没有变快。

什么意思呢?举个例子:虽然20年前一个盘最大的存储空间只有100MB,但是读取完整磁盘只需要1分钟。如今虽然磁盘容量可以轻易的变成1TB、1PB,然而读取完整个盘的数据需要数小时之上。

这背后的问题在于技术发展的限制:磁头在磁道上移动速度的增速远远低于磁盘容量的增长。用通俗的话来说就是,仓库的面积已经从10平米扩展到100平米甚至到1000平米了,但是一个搬运工一天搬运货物的速度并没有显著的提升,所以虽然仓库的容量越来越大,但是搬完整个仓库的货物需要的时间却越来越多。

不过好在我们还有另一个好消息:带宽逐渐变得廉价。相比20年前,GB带宽的光纤已经非常普遍,网络能够实现一秒传输,数据量已经远远超过了整块盘的容量。于是一个大胆的想法被提出来了:既然读取完一个盘的数据需要几个小时,那把数据分成N份,分别放在不同的机器上并行读取,是不是一秒钟就读取完了?

采用网络并行的方式进行读取,将瓶颈从磁头移动转移到了网络,而要增加一条高速带宽,已经不需要付出多么大的代价。

还是仓库的例子,既然一个搬运工速度这么慢,搬完1000平米仓库需要1000分钟,那么我用1000个搬运工搬1000平米是不是1分钟就完了?这个时候影响搬运工的,仅仅是大门的大小,需要同时容纳1000个搬运工进出而已,但是开个大门似乎成本并不高,大不了把四面的墙都拆了做成门嘛。

MR一代

一个优秀的思想被提出来后,总会有许多追随者尝试将其落地,Google率先丢出了三大论文:BigTable、GFS、MapReduce,从理论上讲述了在分布式下如何做到数据的存储、计算,甚至提出了可以在分布式下做结构化的检索。

三大论文开启了分布式计算的时代,然而对于工程界来说,仅有三篇论文并不足以解决生产上的问题,Google并没有将内部实现的内容进行开源,于是另一帮团队:Yahoo,自行根据论文进行实现,而后将其贡献给Apache,逐渐发展成时至今日依旧如日中天的:HDFS、Mapreduce、HBase。

其中尤为重要的分布式计算模型:MapReuce,我们常称为第一代MR,也就是:MRV1。

上图是MRV1的主要架构图,我们可以看到,在MRV1里面,主要分为两个部分:运行环境和编程模型,所谓的运行环境,指的是用来进行分布式任务调度、资源分配等任务运行过程中涉及到的信息,而编程模型,则指的是提供给开发人员进行开发的接口。

对于MRV1来说,它的运行结构图如下所示:

可以看到,在MRV1里面,当我们的一个任务被提交上去之后,由统一的调度器进行任务的监控、分发,以及资源的申请、回收控制等操作。

MRV1有着明显的两个阶段:Map和Reduce,Map阶段主要负责处理输入,每一个Map任务对应一个分片的数据,而后将数据送入到一个特有的数据结构:环形缓冲区。所谓的环形缓冲区,是用来记录数据和索引的一个区域。当环形缓冲区快要溢出的时候,数据将会被落地到磁盘。在数据输入完成后,将会调用用户自己实现的map函数,而后通过与jobtracker的通信,保持着联系,然后分别进入到reduce的阶段,renduce阶段会汇集所有的数据,这个动作在广义上会被很多人称为:shuffle。实际上shuffle并不是reduce才发生的,对于MR来说,从数据从HDFS上加载开始,shuffle就已经开始了,一直伴随到reduce结束。

MRV1类似于工厂生产辣椒酱,很多工人负责把流水线送到自己身边的辣椒切碎,这个就是Map操作,所有工人切碎的辣椒汇集在一起做成辣椒酱,这个就是Reduce操作。也许某个工人把辣椒切成块的速度赶不上流水线送给他辣椒的速度,那么他就需要把辣椒从流水线拿下来放在他的自己的某个地方存着慢慢切,这个动作就相当于shuffle操作。因为最后汇总会等到所有的人都把辣椒切成块之后再处理,所以如果有一个人没有完成,就需要等待,这个时候就发生了我们常说的,数据倾斜。

MR二代

MRV1是统一管理资源的,类似于一家公司的所有决策都需要通过CEO来发出指令,所有人都听命于CEO,每个人做什么事全都是CEO一一安排,所以如果CEO忙不过来了,或者有事联系不上了,整个组织就成了无头苍蝇、完蛋了。

因此对于MRV1来说,虽然它实现了一个并行计算模型,但是其暴露出来的问题也显而易见:

  • 固化的两阶段模式,限制了迭代任务的进行
  • 多次数据落地,整个运行时间大大延长
  • 所有任务由统一的jobtracker调度,存在单点故障。
  • 对资源的控制不到位,没有明确的任务优先级
  • 资源利用不合理,例如在V1里面,资源分为map solt和reduce solt,导致运行map的时候,reduce的solt全部闲置
  • 安全控制

在这些问题逐渐暴露出来后,有很多补救的措施逐渐出现,例如Tez就是一个非常好的例子,它通过接管MRV1的输入和输出,减少其落地到磁盘的动作,目前Tez已经是Hive的内置计算模型。

但是这些补救框架,并不能从根本上解决MRV1的问题,于是第二代MR被研究出来,也就是MRV2,那么对于MRV2来说,它是怎么做的呢?既然一个公司全靠CEO去安排任务和进行管理有风险,那么我们就把公司的所有人分成N个小团队,每个团队有自己的Lead负责进行工作安排,CEO干什么呢?CEO只负责把要做的事情丢给小团队的Lead,小团队的Lead自己去安排手下的人干活。

大多数时候我们对MRV2这个名字并不熟悉,但是我们一定熟悉一个名字:Yarn。Yarn就是MRV2下最核心的功能。

通过上面的图我们发现,对于MRV2来说,它的资源的申请、控制、回收,不再由统一的jobtracker(前面举例中的CEO)来调度了。在MRV2里面,它产生了几个新的概念:

  • Resource Manager:负责统一管理所有资源
  • Application Master:负责一个任务的监控、资源分配、回收等工作(前面例子中的小团队Lead)
  • Node Manager:各个节点的资源监控

这里面并没有提到Yarn,因为Yarn并不是一个技术,而是一个概念,代表V2里面整个任务调度和资源管理系统。我们合并起来统一称为:Yarn。

我们可以对比一下MRV1和MRV2的机构图:

在MRV2里面,依旧分为两个部分:运行环境和编程模型。然而不一样的地方在于,每一个应用程序需要实现自己的Application Master,也就是资源管理系统。Resource Manager进行一次统一的资源分配,由Application Master自己去决定怎么把资源分给每一个Task,在实际开发中,我们发现自己似乎并没有写过资源分配相关的代码,MR的代码依旧可以运行,那是因为MRV2里面,默认提供了MR的Application Master,在MRV2里面,API也发生了变化,而为了兼容MRV1,分别存在两套API。

同时由于MRV2的超高思想,将整个资源调度独立出来,这带来一个好处,那就是Yarn不单单能调度MR计算引擎,还能调度其他计算引擎,例如Spark。虽然目前有Mesos,但是大多数情况下我们还是会选择采用Yarn去作为资源调度器。

Spark分布式计算模型

看起来似乎MRV2向前迈进了一大步,解决了不少问题,然而对于MRV2来说,依然存在它无法跨越的问题。首先为了兼容MR计算模型,它依然保留着两阶段计算的模型,因为对迭代计算基本乏力。MR模型就像一个工厂流水线要生产辣椒酱,要先把辣椒切碎,然后再汇集起来做成辣椒酱,固定的2步操作,如果想在切碎之前再做点啥,或者做成辣椒酱之后再贴个标签啥的,MR模型就支撑不了,因此“需要任意灵活的进行迭代”这一需求就出来了,这个就是Spark的特点。

同时,MR的核心思想是:运行在廉价服务器上,挪数据,所以对于实时计算,MVR2基本抓瞎。

在这些问题之上,Spark诞生。Spark的思想比较简单:挪计算不挪数据。既然要挪计算,那怎么去描述这个计算呢?于是通过RDD封装一个针对数据对应关系记录,在这个封装之上来记录计算。所以在Spark里面,操作分为两类:Action和Transformation。

为什么会有这两类操作?我们可以想一下,如果数据被分散在100个阶段,我们需要做的是查询某个字段大于0的数据,那么这个计算根本不用把数据汇集在一起,统一过滤,分别在不同节点进行过滤就行了。

而如果我们的操作是统计共有多少条数据,则需要将数据汇总,所以对于Spark来说,Action才真正会触发“挪数据”这个动作,Transformation只是做了一个标记转换。我们对Spark的各种调优,大部分时间也是在尽量减少Action的操作。由于在Spark里面,RDD是只读的,所以每一次操作,都会产生一个新的RDD,因此可以形成一系列的RDD依赖,我们也叫RDD链。

模型训练

模型训练更多的偏向于AI领域,在AI领域有两个明显的分支:概率论和神经网络。在计算能力欠缺的时候,概率论模型是最为普遍的做法,但是近年来发展起来的计算能力,让深度神经网络模型逐渐的展现出风采,很多框架都表明自己就是一个深度学习框架。

模型训练本质上是对数据特征的提取,训练本身和大数据没有必然的关系,但是却相辅相成,数据量越大,提取的特征越多,模型训练出来的效果自然越好,然而数据量越大,对计算的要求就越高,也正因为如此,对模型的探索始终是在小数据、抽样领域进行尝试。

那么什么是特征呢?举个例子,我们如果想要预测一个人能活多少岁,最简单的办法就是返回已知去世的人的平均年龄,无论是谁都返回这个值,要做这样的系统当然没有问题。但是仔细观察就会发现,男性能活多少岁和女性似乎不一样,那么我们可以简单的修改一下,在预测之前先判断一下性别,如果是男的就返回男的平均,女的则返回女性的平均。在这里我们已经无形的用了性别这个特征,是因为我们认为性别对结果是有影响的,而训练就需要找出无数个这样的特征。

然而目前对于大数据的处理能力,似乎已经发展到了一个非常好的阶段,至少在分布式计算上,理论上是可以通过水平扩展无限的增加计算能力。

可是模型的训练和应用在工程中的发展一直不是那么顺利,大约总结起来有如下几个原因:

  • 门槛较高,首先需要有比较专业的背景知识,同时还需要具备较强的编程能力,方能将其应用于工程之上。
  • 对于模型训练来说,没有大数据量的支持,生产上的效果始终差强人意,而数据量增大,如何去处理数据又成了另外一个领域的问题,能够同时处理好两方面的问题,人员较少。
  • 在实际工程中,我们获取到的数据集,往往不是训练模型直接能用的,要达到能够直接用于训练模型,还需要非常多的额外处理,这些代价甚至会高于模型训练本身,因此让模型训练这件事的成本变高。
  • 部分使用者,往往并没有达到模型训练的程度,例如连基本的数据平台都不存在,茫然的使用模型,导致效果不如预期,而将结果归结于模型本身的好坏之上。

虽然模型训练的发展过程中有诸多问题,但是依旧能够看到其在向前发展,目前来说,基于GPU的训练,已经成了所有做模型训练的人的标配,Google甚至研发了自己的GPU:TPU。而很多芯片研发公司,也在致力于研究开发出专门用于模型训练的芯片。

对于模型训练来说,目前一般会有两种做法:

  • 单机模型训练
  • 分布式模型训练

单机模型训练

所谓的单机训练,其实就是在一台机器上训练了,对于单机模型训练来讲,瓶颈主要在于提升单机的性能配置,例如不停的提高单个GPU的计算能力。而对于数据来说,大部分都是利用本地数据,虽然我们可以读取分布式文件系统的数据,但是实际上还是经过了shuffle操作,将数据读取到本地,而模型的训练,都是全程单机训练,我们可以通过各种优化算法,例如奇异值分解等手段,来降低计算成本。

分布式模型训练

对于单机训练来说,单个GPU,始终会陷入瓶颈,所以对于模型训练,也有人开始尝试,是否可以分布式训练?

模型的分布式,相对于其他分布式计算会困难许多,首先模型依赖于数据,而模型本身的计算又要依赖于GPU,那么要如何将数据和计算能力结合?

对于目前来讲,模型的分布式一般会有以下几种做法:

  • 数据分布式训练
  • 模型分布式训练
  • 混合训练

上面的图片比较形象的描述了几种不同的训练方式,首先对于数据分布式来说,每一个节点都有一个完整模型的副本,而对于模型分布式来说,模型的计算会被分散到不同的节点上,例如Tensorflow就通过图形化的表达方法,将计算描述为一个图,然后再判断图中的哪些计算可以并行运行,分别拆分到不同的节点上进行训练,从而达到分布式训练的效果。在混合训练中,模型训练会被分散,同时数据也会分散,无论是哪种分布式训练,最终都会涉及一个操作:模型的归一。在目前来说,有不同的做法,可以将模型最终归一,例如集成算法就是逻辑上实现了模型的归一。

结尾

对于大数据和人工智能来讲,现在仅仅是萌芽时期,后面还有大量的工作要做,而模型的训练无论是单机还是分布式,都还没有达到真正稳定的生产批量效果,这些挑战,不仅仅来自于技术的实现,同时也来自于业务的配合,如何利用现有的技术能力,将其推广到业务上解决问题,才是重点需要关注的地方。


更多精彩洞见,请关注微信公众号:思特沃克

Share