Introduction to Core Spark Concepts

  • driver program:
    1. 在集群上启动一系列的并行操作
    2. 包含应用的main函数,定义集群上的分布式数据集,操作数据集
    3. 通过SparkContext对象访问spark,这表示了与计算集群的连接
  • executors
    1. the place to run the operations
    2. Spark automatically takes ur function and ships it to executor nodes.

Programming with RDDs

  • RDD: spark's core abstraction for working with data.
  • RDD简单来说就是元素的分布式集合
  • 在Spark中所有的工作都可以表示成创建一个新的RDDs,转换已有的RDDs,或者是在RDDs上运行operations

RDD Basics

  • An immutable distributed collection of objects.
  • 每个RDD被split成多个partitions,每个partition可能在cluster的不同节点上被计算
  • RDD的创建:
    1. loading一个外部数据集
    2. distributing对象集合(eg: a list or set)
  • RDD操作:(区分这两种操作的原因是Spark的计算是lazy fashion的

    1. transformations:从原RDD创建一个新的RDD
    2. actions:基于RDD计算一个result,这个结果要么返回给driver program,要么存储到外部存储系统(eg: HDFS)
  • RDD.persist():由于缺省情况下,每次运行action的时候RDDs是重新计算的。如果对RDD进行persist,那么该RDD会persist到内存(或disk),下次action的时候可以reuse。

Creating RDDs

  • parallelize()
val lines = sc.parallelize(List("pandas", "I like pandas"))
  • textFile()
val lines = sc.textFile("/path/to/README.md")

RDD Operations

  • Transformation & Action

Transformations

  • Compute lazily
  • 没有改变原RDD(immutable),而是生成了新的RDD,spark会保存这一系列依赖关系(lineage)

Actions

  • Actually do something with our dataset

Passing Functions to Spark

  • Scala: we can pass in functions defined inline, references to methods, or static functions
  • Scala: 我们所传送的函数和其中的数据引用需要被序列化(实现Java的Serializable接口)
  • 如果我们pass一个对象中的函数,或者包含了对象中的字段的引用(eg: self.field),spark会把整个对象发送给worker nodes,这会远大于你所需要的信息。并且如果你的对象不能持久化(pickle in python)的话,会导致是你的程序失败。举一个python的例子:

  错误示范如下:

  正确示范:(提取对象中你所需的字段为局部变量,然后传进去)

  • 同样的,对scala我们也要尽量避免上述情况,而且要注意的是在scala中不需要显示的self.或者this.,所以这种情况显得很不明显,但仍然要注意。举个栗子

  如果在scala中出现了NotSerializableException,那么多半是因为引用了一个不可序列化的类中的变量或字段。所以,传送一个局部的可序列化的变量或函数才是安全的。

  • Any code that is shared by RDD transformations must always be serializable.

Common Transformations and Actions

Basic RDDs

  • 我们首先介绍基本的RDD操作,它们可以执行在所有RDDs上而不用管数据

Element-wise transformations

  • map() and filter()
  • flatMap(): 为每一个输入元素产生多个输出元素。返回的是一个迭代器iterator
val lines = sc.parallelize(List("hello world", "hi"))
val words = lines.flatMap(line => line.split(" "))

Psedudo set operations

  • 一些简单的集合操作:(需要RDDs是同一类型的)

    • RDD1.distinct()  --> 十分昂贵的操作,需要shuffle all data over the network
    • RDD1.union(RDD2)  --> 最简单的集合操作,会保留原RDD中的重复值
    • RDD1.intersection(RDD2) --> 需要去重(来识别共同元素),因而也需要shuffle
    • RDD1.substract(RDD2)  --> perform shuffle
    • RDD1.cartesian(RDD2)  --> returns all possible pairs of (a, b) where a is in the source RDD and b is in the other RDD .十分昂贵
  • 为什么叫psedudo即假的集合操作呢,因为这里的集合丢失了一个重要特性:uniqueness即元素的唯一性。因为我们经常有duplicates

Actions

  • reduce() & fold() :都需要返回值和RDD中的元素保持同一类型。

  fold()接收与reduce接收的函数签名相同的函数,另外再加上一个初始值作为第一次调用的结果.

val sum = rdd.reduce((x, y) => x + y)
  • aggregate(): frees us from the constraint of having the return be the same types as the RDD we are working on.

  aggregate的函数原型:

def aggregate [U: ClassTag] (zeroValue: U) (seqOp: (U,T)=>U,combOp: (U,U)=>U):U

  可以看到,(zeroValue: U)是给定的一个初值,后半部分有两个函数,seqOp相当于是在各个分区里进行的聚合操作,它支持(U, T) => U,也就是支持不同类型的聚合。comOp是将sepOp后的结果聚合,此时的结果全部是U类,也就是只能进行同构聚合。

  一个经典的例子是求平均值。即先用seqOp求出各个分区中的sum和个数,再将seqOp后的结果聚合得到总的sum和总的个数。

  • collect(): 返回整个RDD中的内容,常用于单元测试,因为它需要你的整个数据集能够fit on a single machine.
  • take(n): 返回RDD中的n个元素,并且试图最小化所访问的partition数,所以它可能会返回一个biased collection。
  • takeSample(withReplacement, num, seed): allows us to take a sample of our data either with or without replacement.
  • foreach(): 可以允许我们在每个元素上执行操作or计算,而不需要把元素送回driver

Converting Between RDD Types

  • 一些functions只在某些特定类型RDD上可用。比如mean(), variance()只用于numericRDDs, join()只用于key/value pair RDDs.
  • 在scala和Java中,这些方法未在标准RDD类中定义,因此为了访问这些附加的功能,我们需要确保我们得到了正确的specialized class。

Scala

  • 在scala中。RDDs的转换可以通过使用隐式转换(using implicit conversions)来自动进行。
  • 看一段RDD.scala源码中的介绍
  • 关于scala隐式转换: 当对象调用类中不存在的方法或成员时,编译器会自动将对象进行隐式转换
  • 隐式转换带来的confusion:当你在RDD上调用mean()这样的方法时,你会发现在RDDclass 的Scaladocs中找不到mean()方法,但是该方法能成功调用是由于实现了RDD[Double]到DoubleRDDFunctions的隐式转换。

Persistence(Caching)

  • As discussed earlier, Spark RDDs是惰性求值的,如果我们想要多次使用同一个RDD的话,Spark通常会每次都重新计算该RDD和它所有的依赖。这对于迭代算法是十分昂贵的。
  • 一个比较直观的例子如下,每次action的时候都会重新计算:
  • 为了避免多次重复计算同一个RDD,我们可以让Spark来persist数据。这样的话,计算该RDD的那个节点会保存它们的partition。
  • 如果有数据持久化的节点fail掉了,Spark会在需要的时候重新计算丢失的partitons。当然我们也可以通过在多个节点保存副本的方式来避免节点故障时的slowdown。
  • Spark有很多levels of persistence供选择。
  • Level Space Used CPU time In Memory On Disk Comments

    MEMORY_ONLY

    High Low Y N  

    MEMORY_ONLY_SER

    Low High Y N  

    MEMORY_AND_DISK

    High Medium Some Some Spils to disk if there is too much data to fit in memory.

    MEMORY_AND_DISK_SER

    Low High Some Some

    Spills to disk if there is too much data to fit in memory. Stores serialized representation in memory.

    DISK_ONLY

    Low High N Y  
  • 在Java和scala中,缺省的情况下persist()回将未序列化的对象数据保存在JVM的堆中。
  • 如果你试图在内存中cache过多的数据,Spark将会自动驱逐旧的partitions,使用最少最近使用(Least Recently Used, LRU)缓存策略。对于MEMORY_ONLY level,下次访问的时候会重新计算这些被驱逐的分片。
  • 由于Spark'的各种机制,无论使用哪种level,你都可以不用担心job breaking。但是缓存不必要的数据将会导致有用数据被驱逐,从而增加重计算的时间。
  • Spark提供了unpersist()方法可以让你手工地将RDD移除缓存。
  • Off-heap caching is experimental and uses Tachyon. If you are interested in off-heap caching with Spark, take a look at the Running Spark on Tachyon guide.

<Spark><Programming><RDDs>的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. 基于散列的集合 HashSet\HashMap\HashTable

    HashSet\HashMap\HashTable 1 基于散列的集合 2 元素会根据hashcode散列,因此,集合中元素的顺序不一定与插入的顺序一致. 3 根据equals方法与hashCode方 ...

  2. Roman To Integer leetcode java

    问题描述: Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range fr ...

  3. 使用scp上传和下载文件

    利用scp传输文件 1.从服务器下载文件 scp username@servername:/path/filename /tmp/local_destination 例如scp codinglog@1 ...

  4. 牛客挑战赛 30 A 小G数数

    题目链接:https://ac.nowcoder.com/acm/contest/375/A 分析:我写的时候竟然把它当成了DP....... 还建了个结构体DP数组,保存一二位,不知道当时脑子在抽啥 ...

  5. 先天性肾上腺增生症(ACH)

    先天性肾上腺增生症 类型 症状 并发症 治疗 情感支持 产前筛查 预防 什么是先天性肾上腺皮质增生症? 先天性肾上腺增生症(CAH)是一组影响肾上腺的遗传性疾病.肾上腺产生激素皮质醇和醛固酮.CAH是 ...

  6. 『计算机视觉』FPN:feature pyramid networks for object detection

    对用卷积神经网络进行目标检测方法的一种改进,通过提取多尺度的特征信息进行融合,进而提高目标检测的精度,特别是在小物体检测上的精度.FPN是ResNet或DenseNet等通用特征提取网络的附加组件,可 ...

  7. 移动端自动化测试-Mac-IOS-Appium环境搭建

    第一步 安装JDK,本机如果带有1.7及以上版本的,则可忽略此安装步骤. 百度下载JDK,并配置环境变量 vim ~/.bash_profile 检查是否安装成功 java -version 第二步 ...

  8. 更改 Windows 软件默认安装位置教程

    在打开的“运行”窗口中,输入命令regedit,然后点击确定按钮 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion 百度 ...

  9. Win10更改CMD控制台的代码页和字体和字号

    注意:936(简体中文)时,指定Consolas等英文字体将无效,会自动变为“新宋体”. 代码页:若是UTF8(65001)应改为:0000fde9 字号:000e0000 -> 12 cmd_ ...

  10. C# 3.0 / C# 3.5 扩展方法

    概述 扩展方法是一种特殊的静态方法,可以像扩展类型上的实例方法一样进行调用,能向现有类型“添加”方法,而无须创建新的派生类型.重新编译或以其他方式修改原始类型. 扩展方法的定义实现: public s ...