Spark 的见解 & 优化 (三)

本贴最后更新于 2331 天前,其中的信息可能已经沧海桑田

Shuffle 操作
牵扯到跨节点的网络传输以及 IO 操作,是复杂且昂贵的操作,所以后续对它的优化是重中之重

In Spark, data is generally not distributed across partitions to be in the necessary place for a specific operation. During computations, a single task will operate on a single partition - thus, to organize all the data for a single `reduceByKey` reduce task to execute, Spark needs to perform an all-to-all operation. It must read from all partitions to find all the values for all keys, and then bring together values across partitions to compute the final result for each key - this is called the shuffle

 概括来说某个算子需要其他分区的结果集的时候,将其他分区的结果传递汇总的过程就称之为 Shuffle.所以说 sort,distinct,reduce,group,aggregate 等都会产生 Shuffle 操作。

窄/宽依赖

 窄依赖:父 RDD 中,每个分区内的数据,都只会被子 RDD 中特定的分区所消费,父子分区消费关系为 1 对 1
 宽依赖:父 RDD 的每个分区都可能被多个子 RDD 分区所消费,父子分区消费关系为 1 对 N
 宽依赖和窄依赖如下图所示:

 相对于宽依赖,窄依赖对优化很有优势,主要有以下几点:
 1)窄依赖不会产生 Shuffle 操作,所以不会像宽依赖那样有昂贵的 IO 操作以及网络传输。
 2)RDD 分区丢失的时候,窄依赖只要计算对应的子分区对应的父分区即可,而宽依赖的子分区的数据可能来源于多个父分区,会产生额外的冗余计算,极端情况下,可能全部父分区都要重新计算。

 常用的窄依赖算子:
 map,mapToPair,mapPartitions,filter,union,flatMap,flatMapToPair,mapValues,flatMapValues,join(父 RDD 是 hash-partitioned)
 常用的宽依赖算子:
 sort,distinct,reduce,group,aggregate,partitionBy,join(父 RDD 不是 hash-partitioned)

分区策略

 为了保证数据的均匀分布,spark 有 2 种分区策略,一种是 hash 分区,一种是范围分区.

 1)hash 分区(HashPartitioner),spark 的默认分区策略。

// 部分代码 public int getPartition(Object key) { int var3; if (key == null) { var3 = 0; } else { var3 = .MODULE$.nonNegativeMod(key.hashCode(), this.numPartitions()); } return var3; } //scala代码 def nonNegativeMod(x: Int, mod: Int): Int = { val rawMod = x % mod rawMod + (if (rawMod < 0) mod else 0) }

 取 key 的 hashCode,然后对分区个数取模,取模后的值就是数据将要进入的分区。如果该值小于 0,则该值再加上分区个数。

 2)范围分区(RangePartitioner)

 这个分区的主要逻辑:
  2-1 抽样,先重整个 RDD 中抽取出样本数据,将样本数据排序(默认升序),计算出每个分区的最大 key 值,形成一个 array[key]类型的数组变量 rangeBounds
  2-2 确定边界,判断 key 在 rangeBounds 中所处的范围,给出该 key 值在下一个 RDD 中的分区 id 下标

public int getPartition(Object key) { Object k = key; int partition = 0; if (.MODULE$.array_length(this.org$apache$spark$RangePartitioner$rangeBounds()) <= 128) { while(partition < .MODULE$.array_length(this.org$apache$spark$RangePartitioner$rangeBounds()) && this.org$apache$spark$RangePartitioner$ordering().gt(k, .MODULE$.array_apply(this.org$apache$spark$RangePartitioner$rangeBounds(), partition))) { ++partition; } } else { partition = BoxesRunTime.unboxToInt(this.org$apache$spark$RangePartitioner$binarySearch().apply(this.org$apache$spark$RangePartitioner$rangeBounds(), key)); if (partition < 0) { partition = -partition - 1; } if (partition > .MODULE$.array_length(this.org$apache$spark$RangePartitioner$rangeBounds())) { partition = .MODULE$.array_length(this.org$apache$spark$RangePartitioner$rangeBounds()); } }

上一篇下一篇

  • Spark

    Spark 是 UC Berkeley AMP lab 所开源的类 Hadoop MapReduce 的通用并行框架。Spark 拥有 Hadoop MapReduce 所具有的优点;但不同于 MapReduce 的是 Job 中间输出结果可以保存在内存中,从而不再需要读写 HDFS,因此 Spark 能更好地适用于数据挖掘与机器学习等需要迭代的 MapReduce 的算法。

    74 引用 • 46 回帖 • 569 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • AWS
    11 引用 • 28 回帖 • 7 关注
  • GraphQL

    GraphQL 是一个用于 API 的查询语言,是一个使用基于类型系统来执行查询的服务端运行时(类型系统由你的数据定义)。GraphQL 并没有和任何特定数据库或者存储引擎绑定,而是依靠你现有的代码和数据支撑。

    4 引用 • 3 回帖 • 11 关注
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    127 引用 • 169 回帖
  • Windows

    Microsoft Windows 是美国微软公司研发的一套操作系统,它问世于 1985 年,起初仅仅是 Microsoft-DOS 模拟环境,后续的系统版本由于微软不断的更新升级,不但易用,也慢慢的成为家家户户人们最喜爱的操作系统。

    228 引用 • 476 回帖 • 1 关注
  • Access
    1 引用 • 3 回帖 • 3 关注
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    8 引用 • 26 回帖 • 2 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 5 关注
  • QQ

    1999 年 2 月腾讯正式推出“腾讯 QQ”,在线用户由 1999 年的 2 人(马化腾和张志东)到现在已经发展到上亿用户了,在线人数超过一亿,是目前使用最广泛的聊天软件之一。

    45 引用 • 557 回帖 • 3 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    209 引用 • 2040 回帖
  • CloudFoundry

    Cloud Foundry 是 VMware 推出的业界第一个开源 PaaS 云平台,它支持多种框架、语言、运行时环境、云平台及应用服务,使开发人员能够在几秒钟内进行应用程序的部署和扩展,无需担心任何基础架构的问题。

    5 引用 • 18 回帖 • 187 关注
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    21 引用 • 31 回帖
  • sts
    2 引用 • 2 回帖 • 241 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    32 引用 • 108 回帖
  • Kubernetes

    Kubernetes 是 Google 开源的一个容器编排引擎,它支持自动化部署、大规模可伸缩、应用容器化管理。

    118 引用 • 54 回帖 • 3 关注
  • Linux

    Linux 是一套免费使用和自由传播的类 Unix 操作系统,是一个基于 POSIX 和 Unix 的多用户、多任务、支持多线程和多 CPU 的操作系统。它能运行主要的 Unix 工具软件、应用程序和网络协议,并支持 32 位和 64 位硬件。Linux 继承了 Unix 以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统。

    954 引用 • 944 回帖 • 1 关注
  • Visio
    1 引用 • 2 回帖
  • SQLite

    SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是全世界使用最为广泛的数据库引擎。

    4 引用 • 7 回帖 • 6 关注
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 676 关注
  • PWL

    组织简介

    用爱发电 (Programming With Love) 是一个以开源精神为核心的民间开源爱好者技术组织,“用爱发电”象征开源与贡献精神,加入组织,代表你将遵守组织的“个人开源爱好者”的各项条款。申请加入:用爱发电组织邀请帖
    用爱发电组织官网:https://programmingwithlove.stackoverflow.wiki/

    用爱发电组织的核心驱动力:

    • 遵守开源守则,体现开源&贡献精神:以分享为目的,拒绝非法牟利。
    • 自我保护:使用适当的 License 保护自己的原创作品。
    • 尊重他人:不以各种理由、各种漏洞进行未经允许的抄袭、散播、洩露;以礼相待,尊重所有对社区做出贡献的开发者;通过他人的分享习得知识,要留下足迹,表示感谢。
    • 热爱编程、热爱学习:加入组织,热爱编程是首当其要的。我们欢迎热爱讨论、分享、提问的朋友,也同样欢迎默默成就的朋友。
    • 倾听:正确并恳切对待、处理问题与建议,及时修复开源项目的 Bug ,及时与反馈者沟通。不抬杠、不无视、不辱骂。
    • 平视:不诋毁、轻视、嘲讽其他开发者,主动提出建议、施以帮助,以和谐为本。只要他人肯努力,你也可能会被昔日小看的人所超越,所以请保持谦虚。
    • 乐观且活跃:你的努力决定了你的高度。不要放弃,多年后回头俯瞰,才会发现自己已经成就往日所仰望的水平。积极地将项目开源,帮助他人学习、改进,自己也会获得相应的提升、成就与成就感。
    1 引用 • 487 回帖 • 1 关注
  • 安全

    安全永远都不是一个小问题。

    199 引用 • 818 回帖
  • 程序员

    程序员是从事程序开发、程序维护的专业人员。

    588 引用 • 3528 回帖 • 1 关注
  • Office

    Office 现已更名为 Microsoft 365. Microsoft 365 将高级 Office 应用(如 Word、Excel 和 PowerPoint)与 1 TB 的 OneDrive 云存储空间、高级安全性等结合在一起,可帮助你在任何设备上完成操作。

    5 引用 • 34 回帖
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    108 引用 • 153 回帖
  • JSON

    JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。易于人类阅读和编写。同时也易于机器解析和生成。

    52 引用 • 190 回帖
  • Redis

    Redis 是一个开源的使用 ANSI C 语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API。从 2010 年 3 月 15 日起,Redis 的开发工作由 VMware 主持。从 2013 年 5 月开始,Redis 的开发由 Pivotal 赞助。

    284 引用 • 248 回帖
  • OpenCV
    15 引用 • 36 回帖 • 8 关注
  • MySQL

    MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。

    693 引用 • 537 回帖 • 2 关注