赞
踩
作为业界主流的大数据处理利器,Spark 的地位毋庸置疑。所以,今天我先带你了解一下 Spark 的特点,再一起来看怎么用 Spark 处理推荐系统的特征。Spark 是一个分布式计算平台。所谓分布式,指的是计算节点之间不共享内存,需要通过网络通信的方式交换数据。Spark 最典型的应用方式就是建立在大量廉价的计算节点上,这些节点可以是廉价主机,也可以是虚拟的 Docker 容器。理解了 Spark 的基本概念,我们来看看它的架构。
从下面 Spark 的架构图中我们可以看到,Spark 程序由 Manager Node(管理节点)进行调度组织,由 Worker Node(工作节点)进行具体的计算任务执行,最终将结果返回给 Drive Program(驱动程序)。在物理的 Worker Node 上,数据还会分为不同的 partition(数据分片),可以说 partition 是 Spark 的基础数据单元。
Spark 计算集群能够比传统的单机高性能服务器具备更强大的计算能力,就是由这些成百上千,甚至达到万以上规模的工作节点并行工作带来的。那在执行一个具体任务的时候,Spark 是怎么协同这么多的工作节点,通过并行计算得出最终的结果呢?
这里我们用一个任务来解释一下 Spark 的工作过程。这个任务并不复杂,我们需要先从本地硬盘读取文件 textFile,再从分布式文件系统 HDFS 读取文件 hadoopFile,然后分别对它们进行处理,再把两个文件join 起来得到最终的结果。这里你没必要执着于任务的细节,只要清楚任务的大致流程就好。在 Spark 平台上处理这个任务的时候,会将这个任务拆解成一个子任务 DAG(Directed Acyclic Graph,有向无环图),再根据 DAG 决定程序各步骤执行的方法。从图中我们可以看到,这个 Spark 程序分别从 textFile 和 hadoopFile 读取文件,再经过一系列 map、filter 等操作后进行 join,最终得到了处理结果。
其中,最关键的过程是我们要理解哪些是可以纯并行处理的部分,哪些是必须 shuffle(混洗)和 reduce 的部分。这里的 shuffle 指的是所有 partition 的数据必须进行洗牌后才能得到下一步的数据,最典型的操作就是图中的 groupByKey 操作和 join 操作。以 join 操作为例,我们必须对 textFile 数据和 hadoopFile 数据做全量的匹配才可以得到 join 后的 dataframe。而 groupByKey 操作则需要对数据中所有相同的 key 进行合并,也需要全局的 shuffle 才能完成。与之相比,map、filter 等操作仅需要逐条地进行数据处理和转换,不需要进行数据间的操作,因此各 partition 之间可以完全并行处理。此外,在得到最终的计算结果之前,程序需要进行 reduce 的操作,从各 partition 上汇总统计结果,随着 partition 的数量逐渐减小,reduce 操作的并行程度逐渐降低,直到将最终的计算结果汇总到 master 节点(主节点)上。可以说,shuffle 和 reduce 操作的触发决定了纯并行处理阶段的边界。
最后,我还想强调的是,shuffle 操作需要在不同计算节点之间进行数据交换,非常消耗计算、通信及存储资源,因此 shuffle 操作是 spark 程序应该尽量避免的。
说了这么多,这里我们再用一句话总结 Spark 的计算过程:Stage 内部数据高效并行计算,Stage 边界处进行消耗资源的 shuffle 操作或者最终的 reduce 操作。
Flink 平台到底是怎么进行流数据处理的呢?我们先来认识 Flink 中两个最重要的概念,数据流(DataStream)和窗口(Window)。数据流其实就是消息队列,从网站、APP 这些客户端中产生的数据,被发送到服务器端的时候,就是一个数据消息队列,而流处理平台就是要对这个消息队列进行实时处理。就像下图所示的那样,上面是来自三个用户的数据,其中一个一个紫色的点就是一条条数据,所有紫色的点按时间排列就形成了一个消息队列。
知道了什么是消息队列,Flink 会怎么处理这个消息队列里的数据呢?答案很简单,就是随着时间的流失,按照时间窗口来依次处理每个时间窗口内的数据。比如图中的数据流就被分割成了 5 个时间窗口,每个窗口的长度假设是 5 分钟,这意味着每积攒够 5 分钟的数据,Flink 就会把缓存在内存中的这 5 分钟数据进行一次批处理。这样,我们就可以算出数据流中涉及物品的最新 CTR,并且根据用户最新点击的物品来更新用户的兴趣向量,记录特定物品曝光给用户的次数等等。
然而,固定窗口有很大的弊端,比如我们往往需要通过 JOIN 连接一个物品的曝光数据和点击数据,以此来计算 CTR。但是,曝光数据是在点击数据之前到达 Flink 的。那如果在分窗的时候,恰好把曝光数据和点击数据分割在了两个窗口,那点击数据就不可能找到相应的曝光数据了。
为此,Flink 提供了多种不同的窗口类型,滑动窗口(Sliding Window)也是我们经常会用到的。滑动窗口的特点是在两个窗口之间留有重叠的部分,Flink 在移动窗口的时候,不是移动 window size 这个长度,而是移动 window slide 这个长度,window slide 的长度要小于 window size。因此,窗口内部的数据不仅包含了数据流中新进入的 window slide 长度的数据,还包含了上一个窗口的老数据,这部分数据的长度是 window size - window slide。只要我们使用滑动窗口,之前问题就迎刃而解了。因为两个窗口重叠的部分给我们留了足够的余量来进行数据 JOIN,避免数据的遗漏。事实上,除了固定窗口和滑动窗口,Flink 还提供了更丰富的窗口操作,比如基于会话的 Session Window,全局性的 Global Window。除此之外,Flink 还具有数据流 JOIN,状态保存特性 state 等众多非常有价值的操作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。