flink和spark处理数据方式区别,spark和flink的基本数据模型

  flink和spark处理数据方式区别,spark和flink的基本数据模型

  今天是星火特辑第四篇。让我们来看看一对RDD。

  定义

  在以前的文章中,我们熟悉RDD的概念,以及RDD的基本变换和行为操作。今天,让我们来看看RDD非常常见的PairRDD。也被称为键值对RDD,可以理解为KVRDD。

  我很了解KV。是键和值的组合。比如python dict或者C和Java映射的基本元素就是键值对。与以前的基本RDD相比,pariRDD支持更多的操作,并提供相对更灵活和复杂的功能。例如,可以根据键进行聚合,或者计算交点。

  所以pairRDD的数据类型只是KV结构的RDD,内涵不是很丰富,不用担心。

  Pairdd转换操作

  RDD对也是一个RDD,所以前面描述的RDD转换操作当然也可以使用。两者的关系类似于类继承的关系。RDD是父类,而RDD对是实现一些新功能的子类。子类可以调用父类中的所有方法,但是父类不能调用子类中的方法。

  打电话的时候要注意。我们对RDD的数据格式是KV的二进制群,所以我们传递的函数一定是二进制群数据的函数。否则,操作结果可能会有问题。以下是一些最常见的转换操作。

  为了简化演示,您可以使用固定的RDD来执行各种转换操作,并直观地理解这些转换操作是干什么的。

  ex1=sc.parallelize ([ 1,2 ]、[ 3,4 ]、[ 3,5 ]).

  复制代码

  键、值和排序键

  这三种变换操作应该是最常见最简单的,简单到我们可以从字面上猜出意思。

  让我们先来看看键和值:

  在我们的RDD中,二项式组的第一个元素被设置为key,第二个元素被设置为value。注意,它不是映射或字典,所以键和值都可以重复。

  SortByKey也很直观。从字面上看,可以看出RDD的数据是按照键值排序的。同样,看看下面的结果。

  映射值和平面映射值

  MapValues不能直接使用,必须作为参数函数传递。这意味着对所有值运行该函数。例如,如果要将所有值转换为字符串,可以执行以下操作:

  flatMapValues的操作与我们的认知略有相悖。我们知道flatMap操作可以分解嵌套数组,但是如何分解嵌套value呢?说到这里,我们的值不一定是数组。这是我们收到的函数的描述。这个计划的操作实际上是函数返回的结果。也就是函数返回迭代器,分散的内容其实就是这个迭代器里的值。

  这样表达对我来说可能有点无聊,但就看一个例子:

  不知道这个结果是否出乎意料,但整个过程就是这样。调用flatMapValues操作返回迭代器。迭代器的内容是范围(x,x ^ 3)。实际上每个键对应这样一个迭代器,然后迭代器的内容被打散,和键组成一个新的对。

  groupByKey,reduceByKey,foldByKey

  这两个功能也很接近,不过我先说第一个。学习SQL的同学应该很了解group by operation的含义。不知道也没关系。group by可以很容易理解为分成合并或桶。也就是说,如果具有相同键值的值被组合成一个,则获得键列表的RDD对,并且具有相同键值的值被放入一个列表中。

  请看看下面的例子:

  因为我们调用groupby的结果是一个对象,所以我们必须调用mapValues并将其转换为一个列表才能使用它。否则,无法通过collect获取。

  ReduceByKey类似于groupByKey,只是groupByKey是合并的。但是,reduceByKey被传递给reduce函数,这是reduce执行的结果。请看一个例子:

  在这个例子中,执行累积加法,并且添加具有相同key值的值。

  foldByKey和fold的使用方法差别不大,唯一的区别是增加了基于键值的聚合逻辑。如果将分区的初始值设置为0,则与reduceByKey几乎相同。

  只要你明白foldByKey的初始值是以partition为对象的。

  按键组合

  这也是最核心、最难以理解的转换操作,但我们先来看看它的参数。总共接受五个参数。首先,对我们每个人来说

  第一个参数是createCombiner。

  它的作用是根据我们的需要对值进行初始化和初始化,比如将字符串类型转换为int或者其他操作。我们可以用标记把它写成V=C,其中V是值,C是我们初始化后的新值。

  它会和value一起作为新对传入第二个函数,所以第二个函数接受的参数是(C,V)的二元组。我们要做的就是定义这个二元组的并集,所以第二个函数可以写成(C,v)=c,源代码和在线教程里的注释都是这样写的,但是我觉得可能因为出现了两个C,所以大家很难理解,我觉得可以写成(C,V)=D,这样更好。

  最后一个函数是组合d,所以可以写成(d,d)=d。

  至此,我们似乎明白了它的原理,但似乎有很多问号,总觉得有些地方不太对劲。我想了很久才找到问题的根源。合并的原因是什么?有没有发现第二个函数和第三个函数都是用来合并的?为什么要两次合并?两者有什么区别?如果这个问题不理解,那么它的使用一定是错误的。个人认为这个问题是这次转换操作的核心。没有把这个问题解释清楚的博客是不够清楚的。

  其实这两个合并的逻辑差不多,只是合并的范围不同。第一次合并是为了分区,第二次合并是为了key。在spark中,数据可能存储在多个分区中,所以我们必须合并两次。第一次,我们在分区内集成数据,第二次,我们跨分区合并数据。因为不同分区的数据可能相隔很远,网络传输的时间会太长,所以我们希望传输的数据越少越好,这也是为什么要用两次groupby的原因。

  我们再举一个例子:

  在本例中,我们计算了每个单词的平均出现次数。我们一点一点来看。首先,我们的第一个函数将value转换成一个(1,value)元组。元组的第0个元素表示单词出现的文档数,第1个元素表示在文档中出现的次数。所以第二个函数,也就是组内聚合的函数,我们只需要把出现的文档数加1,累加出现的次数。因为这次聚合的对象都是(1,value)类型的元素,也就是聚合前没有结果。

  在第三个函数中,我们还会累计出现的总次数,因为这个函数处理的结果是每个分区都被聚合了一次。比如苹果在一个分区的两个文档中出现,一共20次,在一个分区的三个文档中出现,一共30次,那么显然我们在五个文档中出现,一共50次。

  因为我们要计算平均值,所以我们必须用出现的总次数除以出现的文档数。最后,map之后,因为得到的还是二元组,所以不能直接采集,需要使用collectAsMap。

  让我们用图表来展示上面的例子,这样就很容易理解了:

  连接操作

  在spark中,除了基本的转换操作,spark还提供了额外的连接操作来配对RDD。通过连接,我们可以轻松地像操作一套RDD。操作方法也很简单,类似于SQL中操作数据表的形式,即join操作。连接操作可分为连接(内连接)、左连接和右连接。

  如果熟悉SQL的话,三者的区别应该非常清楚。它与SQL中的join相同。不熟也没关系,解释起来也不复杂。在连接时,我们经常用一个表连接另一个表,就像两个数相减,我们用一个数减去另一个数。比如A.join(B),我们称A为左表,B为右表。所谓联接,就是将两个表中的某个字段或某些值相同的行联接起来。

  例如,一个表单是学生表单,另一个是考勤表单。只要我们的两个表与学生的id链接,我们就可以获得学生的出勤记录。但既然是集合关联,就会出现数据无法关联的情况。例如,一个学生没有上学,或者出席名单中的学号是错误的。我们有四种方法来处理数据无法关联的情况。第一种方法是丢弃所有的数据,丢弃不能关联的数据。第二种方式是保留所有字段,不能关联的字段记录为NULL。三是左表无法关联的预留,右表丢弃。四是保留右表,丢弃左表。

  下图就是这四种join,非常形象。

  我们来看一些实际例子来体验一下。

  首先创建一个数据集:

  ex1=sc.parallelize([[frank ,30],[bob ,9],[silly ,3]])

  ex2=sc.parallelize([[弗兰克,80],[鲍勃,12],[玛丽,22],[弗兰克,21],[鲍勃,22]])

  复制代码

  接下来,我们分别运行这四种联接,观察联接后的结果。

  从结果中我们可以看到,如果两个数据集中有多个键值相同的数据,spark会将它们成对相乘以进行匹配。

  行动

  最后,让我们来看看RDD的行动。配对rdd也是一个rdd,因此适用于普通RDD的操作也适用于配对rdd。但除此之外,spark还为其开发了独特的移动操作。

  计数键

  CountByKey顾名思义就是根据键值计算每个键值出现的次数,相当于count groupby的SQL语句。让我们看一个具体的例子:

  收藏地图

  这也很好理解。实际上,它意味着最终结果以地图的形式输出:

  从返回的结果可以看出,输出是dict类型的。也就是Python中的‘地图’。

  检查

  这个词看起来很少见,实际上是指根据键值找到对应的值。也就是常用的get函数。当我们传入一个键值时,它会自动返回该键值对应的所有值。如果有多个值,将返回列表。

  摘要

  至此,与配对RDD相关的所有操作都已介绍完毕。Pair rdd在我们日常使用中出现的频率非常高,实现一些复杂的操作非常方便。

  另外,今天的文章包含了很多内容,要彻底理解还需要一点努力。这个不用看文章就能做到,不过没关系。刚开始学的时候,我们只需要对这些API和使用方法有个大概的印象。具体使用细节,我们在使用的时候可以查阅相关资料。

  今天的文章到此为止。如果你认为你有所收获,请关注或转发。你的一点点努力对我很重要。

flink和spark处理数据方式区别,spark和flink的基本数据模型