写点什么

终于有人把大数据架构讲明白了

发布于: 2021 年 07 月 27 日
终于有人把大数据架构讲明白了

本文分享自百度开发者中心终于有人把大数据架构讲明白了


大数据技术其实是分布式技术在数据处理领域的创新性应用,其本质和此前讲到的分布式技术思路一脉相承,即用更多的计算机组成一个集群,提供更多的计算资源,从而满足更大的计算压力要求。


大数据技术讨论的是,如何利用更多的计算机满足大规模的数据计算要求。


大数据就是将各种数据统一收集起来进行计算,发掘其中的价值。这些数据,既包括数据库的数据,也包括日志数据,还包括专门采集的用户行为数据;既包括企业内部自己产生的数据,也包括从第三方采购的数据,还包括使用网络爬虫获取的各种互联网公开数据。


面对如此庞大的数据,如何存储、如何利用大规模的服务器集群处理计算才是大数据技术的核心。


01 HDFS 分布式文件存储架构

大规模的数据计算首先要解决的是大规模数据的存储问题。如何将数百 TB 或数百 PB 的数据存储起来,通过一个文件系统统一管理,这本身就是一项极大的挑战。


HDFS 的架构,如图 31-1 所示。


▲图 31-1 HDFS 架构


HDFS 可以将数千台服务器组成一个统一的文件存储系统,其中 NameNode 服务器充当文件控制块的角色,进行文件元数据管理,即记录文件名、访问权限、数据存储地址等信息,而真正的文件数据则存储在 DataNode 服务器上。


DataNode 以块为单位存储数据,所有的块信息,比如块 ID、块所在的服务器 IP 地址等,都记录在 NameNode 服务器上,而具体的块数据则存储在 DataNode 服务器上。理论上,NameNode 可以将所有 DataNode 服务器上的所有数据块都分配给一个文件,也就是说,一个文件可以使用所有服务器的硬盘存储空间。


此外,HDFS 为了保证不会因为硬盘或者服务器损坏而导致文件损坏,还会对数据块进行复制,每个数据块都会存储在多台服务器上,甚至多个机架上。


02 MapReduce 大数据计算架构

数据存储在 HDFS 上的最终目标还是为了计算,通过数据分析或者机器学习获得有益的结果。但是如果像传统的应用程序那样把 HDFS 当作普通文件,从文件中读取数据后进行计算,那么对于需要一次计算数百 TB 数据的大数据计算场景,就不知道要算到什么时候了。


大数据处理的经典计算框架是 MapReduce。MapReduce 的核心思想是对数据进行分片计算。既然数据是以块为单位分布存储在很多台服务器组成的集群上的,那么能不能就在这些服务器上针对每个数据块进行分布式计算呢?


事实上,MapReduce 可以在分布式集群的多台服务器上启动同一个计算程序,每个服务器上的程序进程都可以读取本服务器上要处理的数据块进行计算,因此,大量的数据就可以同时进行计算了。但是这样一来,每个数据块的数据都是独立的,如果这些数据块需要进行关联计算怎么办?


MapReduce 将计算过程分成两个部分:


一部分是 map 过程,每个服务器上会启动多个 map 进程,map 优先读取本地数据进行计算,计算后输出一个<key, value>集合;另一部分是 reduce 过程,MapReduce 在每个服务器上都会启动多个 reduce 进程,然后对所有 map 输出的<key, value>集合进行 shuffle 操作。所谓的 shuffle 就是将相同的 key 发送到同一个 reduce 进程中,在 reduce 中完成数据关联计算。


下面以经典的 WordCount,即统计所有数据中相同单词的词频数据为例,来认识 map 和 reduce 的处理过程,如图 31-2 所示。


▲图 31-2 词频统计程序 WordCount 的 MapReduce 处理过程


假设原始数据有两个数据块,MapReduce 框架启动了两个 map 进程进行处理,它们分别读入数据。


map 函数会对输入数据进行分词处理,然后针对每个单词输出<单词, 1>这样的<key, value>结果。然后 MapReduce 框架进行 shuffle 操作,相同的 key 发送给同一个 reduce 进程,reduce 的输入就是<key, value 列表>这样的结构,即相同 key 的 value 合并成了一个 value 列表。


在这个示例中,这个 value 列表就是由很多个 1 组成的列表。reduce 对这些 1 进行求和操作,就得到每个单词的词频结果了。


具体的 MapReduce 程序如下:

public class WordCount {
public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable>{
private final static IntWritable one = new IntWritable(1); private Text word = new Text();
public void map(Object key, Text value, Context context ) throws IOException, InterruptedException { StringTokenizer itr = new StringTokenizer(value.toString()); while (itr.hasMoreTokens()) { word.set(itr.nextToken()); context.write(word, one); } }
public static class IntSumReducer extends Reducer<Text,IntWritable,Text,IntWritable> { private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values, Context context ) throws IOException, InterruptedException { int sum = 0; for (IntWritable val : values) { sum += val.get(); } result.set(sum); context.write(key, result); }}
复制代码


上面讲述了 map 和 reduce 进程合作完成数据处理的过程,那么这些进程是如何在分布式的服务器集群上启动的呢?数据是如何流动并最终完成计算的呢?下面以 MapReduce1 为例来看这个过程,如图 31-3 所示。


▲图 31-3 MapReduce1 计算处理过程


MapReduce1 主要有 JobTracker 和 TaskTracker 这两种进程角色,JobTracker 在 MapReduce 集群中只有一个,而 TaskTracker 则和 DataNode 一起启动在集群的所有服务器上。


MapReduce 应用程序 JobClient 启动后,会向 JobTracker 提交作业,JobTracker 根据作业中输入的文件路径分析需要在哪些服务器上启动 map 进程,然后就向这些服务器上的 TaskTracker 发送任务命令。


TaskTracker 收到任务后,启动一个 TaskRunner 进程下载任务对应的程序,然后反射加载程序中的 map 函数,读取任务中分配的数据块,并进行 map 计算。map 计算结束后,TaskTracker 会对 map 输出进行 shuffle 操作,然后 TaskRunner 加载 reduce 函数进行后续计算。


HDFS 和 MapReduce 都是 Hadoop 的组成部分。


03 Hive 大数据仓库架构

MapReduce 虽然只有 map 和 reduce 这两个函数,但几乎可以满足任何大数据分析和机器学习的计算场景。不过,复杂的计算可能需要使用多个 job 才能完成,这些 job 之间还需要根据其先后依赖关系进行作业编排,开发比较复杂。


传统上,主要使用 SQL 进行数据分析,如果能根据 SQL 自动生成 MapReduce,就可以极大降低大数据技术在数据分析领域的应用门槛。


Hive 就是这样一个工具。我们来看对于如下一条常见的 SQL 语句,Hive 是如何将其转换成 MapReduce 计算的。

SELECT pageid, age, count(1) FROM pv_users GROUP BY pageid, age;
复制代码

这是一条常见的 SQL 统计分析语句,用于统计不同年龄的用户访问不同网页的兴趣偏好,具体数据输入和执行结果示例如图 31-4 所示。


▲图 31-4 SQL 统计分析输入数据和执行结果举例


看这个示例我们就会发现,这个计算场景和 WordCount 很像。事实上也确实如此,我们可以用 MapReduce 完成这条 SQL 的处理,如图 31-5 所示。


▲图 31-5 MapReduce 完成 SQL 处理过程举例


map 函数输出的 key 是表的行记录,value 是 1,reduce 函数对相同的行进行记录,也就是针对具有相同 key 的 value 集合进行求和计算,最终得到 SQL 的输出结果。


Hive 要做的就是将 SQL 翻译成 MapReduce 程序代码。实际上,Hive 内置了很多 Operator,每个 Operator 完成一个特定的计算过程,Hive 将这些 Operator 构造成一个有向无环图 DAG,然后根据这些 Operator 之间是否存在 shuffle 将其封装到 map 或者 reduce 函数中,之后就可以提交给 MapReduce 执行了。


Operator 组成的 DAG 如图 31-6 所示,这是一个包含 where 查询条件的 SQL,where 查询条件对应一个 FilterOperator。


▲图 31-6 示例 SQL 的 MapReduce 有向无环图 DAG


Hive 整体架构如图 31-7 所示。Hive 的表数据存储在 HDFS。表的结构,比如表名、字段名、字段之间的分隔符等存储在 Metastore 中。用户通过 Client 提交 SQL 到 Driver,Driver 请求 Compiler 将 SQL 编译成如上示例的 DAG 执行计划中,然后交给 Hadoop 执行。


▲图 31-7 Hive 整体架构


04 Spark 快速大数据计算架构

MapReduce 主要使用硬盘存储计算过程中的数据,虽然可靠性比较高,但是性能却较差。


此外,MapReduce 只能使用 map 和 reduce 函数进行编程,虽然能够完成各种大数据计算,但是编程比较复杂。而且受 map 和 reduce 编程模型相对简单的影响,复杂的计算必须组合多个 MapReduce job 才能完成,编程难度进一步增加。


Spark 在 MapReduce 的基础上进行了改进,它主要使用内存进行中间计算数据存储,加快了计算执行时间,在某些情况下性能可以提升上百倍。


Spark 的主要编程模型是 RDD,即弹性数据集。在 RDD 上定义了许多常见的大数据计算函数,利用这些函数可以用极少的代码完成较为复杂的大数据计算。前面举例的 WorkCount 如果用 Spark 编程,只需要三行代码:

val textFile = sc.textFile("hdfs://...")val counts = textFile.flatMap(line => line.split(" "))                 .map(word => (word, 1))                 .reduceByKey(_ + _)counts.saveAsTextFile("hdfs://...")
复制代码

首先,从 HDFS 读取数据,构建出一个 RDD textFile。然后,在这个 RDD 上执行三个操作:


一是将输入数据的每一行文本用空格拆分成单词;二是将每个单词进行转换,比如 word→(word, 1),生成<Key, Value>的结构;三是针对相同的 Key 进行统计,统计方式是对 Value 求和。最后,将 RDD counts 写入 HDFS,完成结果输出。


上面代码中 flatMap、map、reduceByKey 都是 Spark 的 RDD 转换函数,RDD 转换函数的计算结果还是 RDD,所以上面三个函数可以写在一行代码上,最后得到的还是 RDD。


Spark 会根据程序中的转换函数生成计算任务执行计划,这个执行计划就是一个 DAG。Spark 可以在一个作业中完成非常复杂的大数据计算,Spark DAG 示例如图 31-8 所示。


▲图 31-8 Spark RDD 有向无环图 DAG 示例


在图 31-8 中,A、C 和 E 是从 HDFS 上加载的 RDD。A 经过 groupBy 分组统计转换函数计算后得到 RDD B,C 经过 map 转换函数计算后得到 RDD D,D 和 E 经过 union 合并转换函数计算后得到 RDD F,B 和 F 经过 join 连接转换函数计算后得到最终结果 RDD G。


05 大数据流计算架构

Spark 虽然比 MapReduce 快很多,但是在大多数场景下计算耗时依然是分钟级别的,这种计算一般被称为大数据批处理计算。而在实际应用中,有些时候需要在毫秒级完成不断输入的海量数据的计算处理,比如实时对摄像头采集的数据进行监控分析,这就是所谓的大数据流计算。


早期比较著名的流式大数据计算引擎是 Storm,后来随着 Spark 的火爆,Spark 上的流式计算引擎 Spark Streaming 也逐渐流行起来。Spark Streaming 的架构原理是将实时流入的数据切分成小的一批一批的数据,然后将这些小的一批批数据交给 Spark 执行。


由于数据量比较小,Spark Streaming 又常驻系统,不需要重新启动,因此可以在毫秒级完成计算,看起来像是实时计算一样,如图 31-9 所示。


▲图 31-9 Spark Streaming 流计算将实时流式数据转化成小的批处理计算


最近几年比较流行的大数据引擎 Flink 其架构原理和 Spark Streaming 很相似,它可以基于不同的数据源,根据数据量和计算场景的要求,灵活地适应流计算和批处理计算。


06 小结

大数据技术可以说是分布式技术的一个分支,两者都是面临大量的计算压力时,采用分布式服务器集群的方案解决问题。差别是大数据技术要处理的数据具有关联性,所以需要有个中心服务器进行管理,NameNode、JobTracker 都是这样的中心服务器。


而高并发的互联网分布式系统为了提高系统可用性,降低中心服务器可能会出现的瓶颈压力、提升性能,通常不会在架构中使用这样的中心服务器。


作者:李智慧

来源:大数据 DT(ID:hzdashuju)


关于作者:李智慧,资深架构专家,同程旅行交通首席架构师,曾在 NEC、阿里巴巴、Intel 等知名企业担任架构师,也曾在 WiFi 万能钥匙等企业担任 CTO。长期从事大数据、大型网站的架构和研发工作,领导设计过多个日活用户在千万级以上的互联网系统架构,实战经验丰富。曾设计、开发过 Web 服务器防火墙、分布式 NoSQL 系统、大数据仓库引擎、反应式编程框架等各种类型的软件系统。


>>期待你的加入

>>百度开发者中心已开启征稿模式,欢迎开发者进入了不起的开发者进行投稿,优质文章将获得丰厚奖励和推广资源。

发布于: 2021 年 07 月 27 日阅读数: 1114
用户头像

关注百度开发者中心,收获一手技术干货。 2018.11.12 加入

汇聚百度所有对外开放技术、平台和服务资源,提供全方位支持,助力开发者加速成功,实现开发者、消费者和百度三方共赢。https://developer.baidu.com/

评论

发布
暂无评论
终于有人把大数据架构讲明白了