阅读更多
0x00 前言
引用
数据倾斜是大数据领域绕不开的拦路虎,当你所需处理的数据量到达了上亿甚至是千亿条的时候,数据倾斜将是横在你面前一道巨大的坎。
迈的过去,将会海阔天空!迈不过去,就要做好准备:很可能有几周甚至几月都要头疼于数据倾斜导致的各类诡异的问题。

郑重声明:
  • 话题比较大,技术要求也比较高,笔者尽最大的能力来写出自己的理解,写的不对和不好的地方大家一起交流。
  • 有些例子不是特别严谨,一些小细节对文章理解没有影响,不要太在意。(比如我在算机器内存的时候,就不把Hadoop自身的进程算到使用内存中)
  • 总的来讲个人感觉写的还是比较干货的。
文章结构
  • 先大致解释一下什么是数据倾斜
  • 再根据几个场景来描述一下数据倾斜产生的情况
  • 详细分析一下在Hadoop和Spark中产生数据倾斜的原因
  • 如何解决(优化)数据倾斜问题?
0x01 什么是数据倾斜
简单的讲,数据倾斜就是我们在计算数据的时候,数据的分散度不够,导致大量的数据集中到了一台或者几台机器上计算,这些数据的计算速度远远低于平均计算速度,导致整个计算过程过慢。

一、关键字:数据倾斜
相信大部分做数据的童鞋们都会遇到数据倾斜,数据倾斜会发生在数据开发的各个环节中,比如:
  • 用Hive算数据的时候reduce阶段卡在99.99%
  • 用SparkStreaming做实时算法时候,一直会有executor出现OOM的错误,但是其余的executor内存使用率却很低。
这些问题经常会困扰我们,辛辛苦苦等了几个小时的数据就是跑不出来,心里多难过啊。

例子很多,这里先随便举两个,后文会详细的说明。

二、关键字:千亿级
为什么要突出这么大数据量?先说一下笔者自己最初对数据量的理解:
引用
数据量大就了不起了?数据量少,机器也少,计算能力也是有限的,因此难度也是一样的。凭什么数据量大就会有数据倾斜,数据量小就没有?

这样理解也有道理,但是比较片面,举两个场景来对比:
  • 公司一:总用户量1000万,5台64G内存的的服务器。
  • 公司二:总用户量10亿,1000台64G内存的服务器。
两个公司都部署了Hadoop集群。假设现在遇到了数据倾斜,发生什么?

公司一的数据分时童鞋在做join的时候发生了数据倾斜,会导致有几百万用户的相关数据集中到了一台服务器上,几百万的用户数据,说大也不大,正常字段量的数据的话64G还是能轻松处理掉的。

公司二的数据分时童鞋在做join的时候也发生了数据倾斜,可能会有1个亿的用户相关数据集中到了一台机器上了(相信我,这很常见),这时候一台机器就很难搞定了,最后会很难算出结果。

0x02 数据倾斜长什么样
笔者大部分的数据倾斜问题都解决了,而且也不想重新运行任务来截图,下面会分几个场景来描述一下数据倾斜的特征,方便读者辨别。

由于Hadoop和Spark是最常见的两个计算平台,下面就以这两个平台说明:
一、Hadoop中的数据倾斜
Hadoop中直接贴近用户使用使用的时Mapreduce程序和Hive程序,虽说Hive最后也是用MR来执行(至少目前Hive内存计算并不普及),但是毕竟写的内容逻辑区别很大,一个是程序,一个是Sql,因此这里稍作区分。

Hadoop中的数据倾斜主要表现在、ruduce阶段卡在99.99%,一直99.99%不能结束。

这里如果详细的看日志或者和监控界面的话会发现:
  • 有一个多几个reduce卡住
  • 各种container报错OOM
  • 读写的数据量极大,至少远远超过其它正常的reduce
伴随着数据倾斜,会出现任务被kill等各种诡异的表现。

经验:Hive的数据倾斜,一般都发生在Sql中Group和On上,而且和数据逻辑绑定比较深。

二、Spark中的数据倾斜
Spark中的数据倾斜也很常见,这里包括Spark Streaming和Spark Sql,表现主要有下面几种:
  • Executor lost,OOM,Shuffle过程出错
  • Driver OOM
  • 单个Executor执行时间特别久,整体任务卡在某个阶段不能结束
  • 正常运行的任务突然失败
补充一下,在Spark streaming程序中,数据倾斜更容易出现,特别是在程序中包含一些类似sql的join、group这种操作的时候。 因为Spark Streaming程序在运行的时候,我们一般不会分配特别多的内存,因此一旦在这个过程中出现一些数据倾斜,就十分容易造成OOM。

0x03 数据倾斜的原理
一、数据倾斜产生的原因
我们以Spark和Hive的使用场景为例。他们在做数据运算的时候会设计到,countdistinct、group by、join等操作,这些都会触发Shuffle动作,一旦触发,所有相同key的值就会拉到一个或几个节点上,就容易发生单点问题。

二、万恶的shuffle
Shuffle是一个能产生奇迹的地方,不管是在Spark还是Hadoop中,它们的作用都是至关重要的。关于Shuffle的原理,这里不再讲述,看看Hadoop相关的论文或者文章理解一下就ok。这里主要针对,在Shuffle如何产生了数据倾斜。

Hadoop和Spark在Shuffle过程中产生数据倾斜的原理基本类似。如下图。

大部分数据倾斜的原理就类似于下图,很明了,因为数据分布不均匀,导致大量的数据分配到了一个节点。

三、从数据角度来理解数据倾斜
我们举一个例子,就说数据默认值的设计吧,假设我们有两张表:
  • user(用户信息表):userid,register_ip
  • ip(IP表):ip,register_user_cnt
这可能是两个不同的人开发的数据表,如果我们的数据规范不太完善的话,会出现一种情况,user表中的register_ip字段,如果获取不到这个信息,我们默认为null,但是在ip表中,我们在统计这个值的时候,为了方便,我们把获取不到ip的用户,统一认为他们的ip为0。

两边其实都没有错的,但是一旦我们做关联了会出现什么情况,这个任务会在做关联的阶段,也就是sql的on的阶段卡死。

四、从业务计角度来理解数据倾斜
数据往往和业务是强相关的,业务的场景直接影响到了数据的分布。

再举一个例子,比如就说订单场景吧,我们在某一天在北京和上海两个城市多了强力的推广,结果可能是这两个城市的订单量增长了10000%,其余城市的数据量不变。

然后我们要统计不同城市的订单情况,这样,一做group操作,可能直接就数据倾斜了。

0x04 如何解决
数据倾斜的产生是有一些讨论的,解决它们也是有一些讨论的,本章会先给出几个解决数据倾斜的思路,然后对Hadoop和Spark分别给出一些解决数据倾斜的方案。

注意: 很多数据倾斜的问题,都可以用和平台无关的方式解决,比如更好的数据预处理, 异常值的过滤等,因此笔者认为,解决数据倾斜的重点在于对数据设计和业务的理解,这两个搞清楚了,数据倾斜就解决了大部分了。

一、几个思路
解决数据倾斜有这几个思路:
  • 业务逻辑,我们从业务逻辑的层面上来优化数据倾斜,比如上面的例子,我们单独对这两个城市来做count,最后和其它城市做整合。
  • 程序层面,比如说在Hive中,经常遇到count(distinct)操作,这样会导致最终只有一个reduce,我们可以先group 再在外面包一层count,就可以了。
  • 调参方面,Hadoop和Spark都自带了很多的参数和机制来调节数据倾斜,合理利用它们就能解决大部分问题。
二、从业务和数据上解决数据倾斜
很多数据倾斜都是在数据的使用上造成的。我们举几个场景,并分别给出它们的解决方案。

数据分布不均匀:

前面提到的“从数据角度来理解数据倾斜”和“从业务计角度来理解数据倾斜”中的例子,其实都是数据分布不均匀的类型,这种情况和计算平台无关,我们能通过设计的角度尝试解决它。
  • 有损的方法:
  •         找到异常数据,比如ip为0的数据,过滤掉
  • 无损的方法:
  •        对分布不均匀的数据,单独计算
            先对key做一层hash,先将数据打散让它的并行度变大,再汇集
  • 数据预处理
三、Hadoop平台的优化方法
列出来一些方法和思路,具体的参数和用法在官网看就行了。
  • mapjoin方式
  • count distinct的操作,先转成group,再count
  • 万能膏药:hive.groupby.skewindata=true
  • left semi jioin的使用
  • 设置map端输出、中间结果压缩。(不完全是解决数据倾斜的问题,但是减少了IO读写和网络传输,能提高很多效率)
四、Spark平台的优化方法
列出来一些方法和思路,具体的参数和用法在官网看就行了。
  • mapjoin方式
  • 设置rdd压缩
  • 合理设置driver的内存
  • Spark Sql中的优化和Hive类似,可以参考Hive
0xFF 总结
数据倾斜的坑还是很大的,如何处理数据倾斜是一个长期的过程,希望本文的一些思路能提供帮助。

文中一些内容没有细讲,比如Hive Sql的优化,数据清洗中的各种坑,这些留待后面单独的分享,会有很多的内容。

另外千亿级别的数据还会有更多的难点,不仅仅是数据倾斜的问题,这一点在后面也会有专门的分享。

参考

  • 大小: 157.3 KB
来自: dantezhao
1
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • C#实现ping服务器检测并返回结果支持循环扫描

    C#实现ping服务器检测并返回结果支持循环扫描

  • 用C#实现实现简单的 Ping 的功能,用于测试网络是否已经联通

    用C#实现实现简单的 Ping 的功能,用于测试网络是否已经联通 1. 根据IP地址获得主机名称 /// /// 根据IP地址获得主机名称 /// /// 主机的IP地址 /// 主机名称 public string GetHostNameByIp(string ip)

  • C# ping命令,ping网络状态

    Ping ping = new Ping(); PingReply pingReply = ping.Send("192.168.1.1"); //网络状态 if (pingReply.Status != IPStatus.Success) { ApplicationLog.WriteLog("网络已经断开"); } else if(pingReply.Status == IPStatus.Success) { ApplicationLog.WriteLog("网络状态良好"); } ...

  • 检查网络连接Ping

    Ping是一种常用的测试网络连接的工具,可以测试网络延迟和连接状况,以及判断网络是否可用。在C#中也可以通过系统自带的Ping类来实现Ping功能。

  • C# ping命令的实现方法

    在 C# 中,可以使用命名空间中的Ping类来实现 Ping 命令的功能。下面是一个简单的示例,演示如何使用Ping类来发送 ICMP 请求并获取响应。

  • C#实现ping一个网段

    4循环遍历需要ping的IP地址,调用Ping实例的Send方法进行ping操作。1首先引入System.Net.NetworkInformation命名空间。使用C#中的Ping类来实现ping一个网段。5根据PingReply的Status属性判断ping的结果。3设置Ping选项,如超时时间等。6将结果输出或保存到文件中。2创建一个Ping实例。

  • ICMP协议

    ICMP协议 ICMP(Internet Control Message Protocol)Internet控制报文协议。它是TCP/IP协议簇的一个子协议,用于在IP主机、路由器之间传递控制消息。控制消息是指网络通不通、主机是否可达、路由是否可用等网络本身的消息。这些控制消息虽然并不传输用户数据,但是对于用户数据的传递起着重要的作用。 ICMP使用IP的基本支持,就像它是一个更高级别的协议,但是...

  • C#时实Ping远程服务器,监控网络!

    C#实时Ping远程服务器,监控网络!获得网络状态,记录掉包时间,断线时间!

  • C# 使用 ping 命令获取相关信息

    C# 使用 ping 命令获取相关信息 使用的C# Process对象

  • C# Ping 简单使用

    编程过程中,有时候需要判断主机是否在线,最简单的方法就是使用Windows的Ping命令看看能否ping通。看到网上很多文章,说用C#去调用windows的ping.exe,然后解析返回的字符串。我觉得这种方式太麻烦了,就做一下简单判断,不想弄那么麻烦。 查了一下,C#专门提供了一个Ping类,与Windows下的ping命令类似: 命令空间: System.Net.NetworkInform

  • C#判断联网状态检查电脑联网状态

    Chinar blog :www.chinar.xin InternetGetConnectedState 本文提供全流程,中文翻译 Chinar 的初衷是将一种简单的生活方式带给世人使有限时间 具备无限可能 Chinar —— 心分享、心创新!助力快速利用 C# 判断用户电脑联网状态给新手节省宝贵的时间,避免采坑! Chinar 教程...

  • c#中如何判断已知网络的连接状态?

    下面的示例连接到远程终结点,然后验证该连接。[C#] aSocket.Connect(anEndPoint);if (!aSocket.Connected) {   Console.WriteLine("Winsock error: "      + Convert.ToString(System.Runtime.InteropServices.Marshal.GetLastWin32Error(

  • 使用C# 获取网卡使用率

    下载 Vanara.PInvoke.IpHlpApi Install-Package Vanara.PInvoke.IpHlpApi -Version 1.0.12 由于只是简单使用,所以没做太多研究,只说大概思路 GetIfTable获得网络状态 得到的结果是一个列表,里面包含的很多信息,其中 dwInOctets是进入流量 dwOutOctets是出口流量 分别取到这两个参数的总和,然后等待1秒钟 再重新分别取这两个值的和,就是瞬时流量 var iftab.

  • c# ping网络ip或网站地址 判断网络是否连接

    就是一个判断本机与某个IP地址、某个电脑是否连通,从而可以判断本机是否在某个网段上,也可以通过ping外网的地址来判断本机是否连网,也可以用来检测某个网站是否还存在可以访问。

  • 使用C#写的TCP通讯程序本机调试能连接,但是别的电脑无法连接,已通过ping电脑IP地址确认电脑导通...

    使用C#写的TCP通讯程序本机调试能连接,但是别的电脑无法连接,已通过ping电脑IP地址确认电脑导通。 此时,问题可能出在工程的设置:注意,调试时无法连接有可能是没有勾选下图所示的选项 ...

Global site tag (gtag.js) - Google Analytics