数据倾斜产生,原因及其解决方案

article/2025/8/25 21:55:37

目录

第七章 数据倾斜 

7.1 数据倾斜的产生,表现与原因

7.1.1 数据倾斜的定义

7.1.2 数据倾斜的危害

7.1.3 数据倾斜发生的现象

7.2 数据倾斜倾斜造成的原因

7.3 几种常见的数据倾斜及其解决方案

7.3.1 空值引发的数据倾斜

7.3.2 不同数据类型引发的数据倾斜

7.3.3 表连接时引发的数据倾斜

7.3.4 group by分组时候key值分布不均

7.3.5 count distinct去重的时候key值分布不均

7.3.6 排序过程

7.2.7 数据膨胀引起

7.4 实践与定位


第七章 数据倾斜 

7.1 数据倾斜的产生,表现与原因

7.1.1 数据倾斜的定义

        数据倾斜是指在并行进行数据处理的时候,由于单个partition的数据显著多余其他部分,分布不均匀,导致大量数据集中分布到一台或者某几台计算节点上,使得该部分的处理速度远低于平均计算速度,成为整个数据集处理的瓶颈,从而影响整体计算性能。

7.1.2 数据倾斜的危害

        对于分布式系统来说,理想的处理方式应该是各台机器共同工作,整体耗时随着计算节点数量的增加而线性下降。但在实际情况下,很多机器所分配的任务是不均匀的,例如大部分任务被分配到个别机器上,其他机器只处理小部分任务,则执行效率提升不明显,远低于理想值。由此可见,根据“水桶效应”,分布式系统的计算能力由耗时最长的任务所决定,对于大数据系统来说,可怕的不是大数据量,而是数据倾斜。

        当数据出现数据倾斜的时候,某机器计算耗时远高于其他机器,带来的主要问题有两点:一是整体耗时过大,不能充分发挥分布式系统的并行计算优势;二是部分机器处理的数据量过大,可能导致内存不足,任务失败。

7.1.3 数据倾斜发生的现象

        通过检查日志可以看到,出现数据倾斜主要有一下3种现象:

  • 绝大多数任务执行的很快,但个别Executor执行时间很长,导致整体任务卡在某一阶段不能结束,整体执行时间过长;

  • 原本能够正常执行的Spark作业,爆出内存溢出异常,无法正常产出数据;

  • 个别Reduce处理的数据量与平均数据量相比差异过大,通常可达3倍甚至更多,远远超过其他正常reduce,

7.2 数据倾斜倾斜造成的原因

        数据倾斜产生原因主要有以下几点:数据key值分布不均,机器配置和数据量比例不合理,业务数据本身特性导致。

  • key-value值分布不均

例如join连接,group by分组,distinct去重

  • 机器配置不合理

当机器配置与所需的数据量不相匹配的时候,总会出现部分需要处理的key值数量超出机器处理能力的情况,由此造成Reduce进程卡顿。

  • 业务数据自身特性

除了技术上的原因,业务本身的特性也会导致数据分布不均匀的情况,如不同品牌门店的数据量,订单量。

  • 小文件过多,笛卡尔积造成的数据膨胀等

7.3 几种常见的数据倾斜及其解决方案

7.3.1 空值引发的数据倾斜

  • 问题描述:实际业务中有些大量的null值或者一些无意义的数据参与到计算作业中,表中如果有大量的null值,如果表之间进行join操作,就会有shuffle产生,这样所有的null值都会被分配到一个reduce中,必然产生数据倾斜。

  • 注意:a,b两个表进行join操作,假设a表需要join的字段为null,但是b表需要join的字段不为null,这两个字段根本就join不上,为什么还会放在同一个reduce中呢?我们要注意的是,数据放到同一个reduce中的原因不是因为字段能不能join上,而是因为shuffle阶段的hash操作,只要key值相同,他们就会被拉到同一个reduce中。

  • 解决方案1:直接不让null值参与join操作,也就是不让null值有shuffle阶段

select  *from log ajoin users bon a.user_id is not null and a.user_id = b.user_idunion all select  *from log a where a.user_id  is null;
  • 解决方案2:对null值进行随机赋值。因为null值参与shuffle时的hash结果是一样的,那么我们可以给null值随机赋值(注意:使用concat连接某一个字符串,防止与其他真实数据冲突出现问题),这样他们的hash结果就不一样,就会进到不同的reduce中。

select * from log aleft join users bon case when a.user.id is null then concat(‘hive_’,rand())else a.user_id end= b.user_id;

7.3.2 不同数据类型引发的数据倾斜

  • 问题描述:对于两个表join,表a中需要join的字段key为int,表b中key字段既有string类型,也有int类型。当按照key进行两个表的join操作时,默认的hash操作会按int型的id来进行分配,这样所有的string类型都被分配成同一个id,结果就是所有的string类型的字段进入到一个reduce中,引发数据倾斜。

  • 原因:既有字符串又有int类型的时候,就是很多字符串数据被当做同一个int的id进行分配,导致所有的字符串数据被分配到同一个reduce里面了。

  • 解决方案:如果key值既有string类型也有int类型,默认的hash都会按照int类型来分配,那我们直接把int类型都转为string就好了,这样key字段都为string,hash时候就按照string类型分配了。

7.3.3 表连接时引发的数据倾斜

  • 问题描述:大小表

  • 说明:在map阶段进行join,而不是像普通的join那样在Reduce阶段按照join列进行分发后在每个Reduce节点上进行join,一来省去了Shuffle这个代价,二来不需要分发。

  • 解决方案:将其中做连接的小表(全量数据)分发到所有MapTask端进行join,从而避免了reduceTask,前提要求是内存足以装下该全量数据。也就是说我们在map端进行了join操作,省去了reduce阶段,即没有shuffle过程,没有reduce任务,避免了数据倾斜。(参考:https://www.modb.pro/db/86447)

  • 补充:在map端进行join,其原理是broadcast join,即把小表作为一个完整的驱动表来进行join操作。在通常情况下,需要连接的各个表里面的数据会分布到不同的Map中进行处理。即同一个key对应的value可能存在不同的Map中,这样就必须等到Reduce中去连接。需要使mapJoin能够顺利进行,那就必须满足这样的条件:除了一份表的数据分布在不同的Map中,其他连接的表的数据必须在每个Map中都有完整的拷贝。Map Join会把小表全部读入内存中,在Map阶段直接拿另外一个表的数据和内存中表数据做匹配(这时候可以使用Distributed Cache将小表分发到各个节点上,提供Mapper加载使用),由于在map时进行了join操作,省去了reduce运行的效率也会高很多

7.3.4 group by分组时候key值分布不均

  • 问题描述:由于key值分布不均匀,在使用group by分组的时候产生了数据倾斜

  • 解决方案:采用两阶段聚合的方式。两阶段聚合指的是先局部聚合再全局聚合。局部聚合时候给每个key值加上随机前缀进行打散,原本相同的key值会变成不同的新key值,便可以让原来由一个task处理的数据根据加上随机前缀后的新key值分散到多个Task上做聚合,从而缓解单个task处理数据量过多的问题。再去除随机前缀做全局聚合,既可以得到最终结果。

  • 优点:对于聚合类操作导致的数据倾斜效果明显,可以大幅缓解数据倾斜问题,提升作业执行效率。缺点在于只适用于聚合类场景,不适用于join等其它操作。

 

7.3.5 count distinct去重的时候key值分布不均

  • 问题描述:大多数是因为空值造成的。

  • 解决方案1:将空值部门与非空值部分拆分成两个部分单独处理后再做合并

  • 解决方案2:使用sum()   group by来替代count(distinct )。

7.3.6 排序过程

问题描述:order by会对输入做全局排序,当只有一个reducer的时候,如果输入规模较大,会消耗较长的计算时间。

解决方案:?

7.2.7 数据膨胀引起

  • 问题描述:在多维聚合计算时,如果进行分组聚合的字段过多,如下:

select a,b,c,count(1) from log group by a,b,c with rollup;

  • 解决方案:通过参数hive.new.job.grouping.set.cardinality配置的方式自动控制作业的拆解,该参数默认值是30,表示针对grouping sets/rollups/cubes这类多维聚合的操作,如果最后拆解的键组合大于该值,会启用新的任务去处理大于该值之外的组合,某个分组聚合的列有较大的倾斜,可以适当调小该值。

7.4 实践与定位

        因为实际上,绝大部分的数据倾斜都产生在Shuffle阶段,我们治理的办法一般是发现问题--定位问题--根据问题原因分类优化(例如join,group by , count distinct)

        我们首先找到执行时间较长的stage,判断stage是否倾斜。倾斜的指标:stage的其task的执行时长和处理数据量的(max/mid)的值都大于2,且该stage的执行时长大于1800s)可能会有多个执行执行时间比较长的stage存在数据倾斜,请分别定位治理。注意,存在数据倾斜的stage不一定执行时间最长。

        找到stage后,根据提示信息即可定位大致的问题,找到SQL问题位置,然后分析表的key值分布,表的大小,确定问题,进行程序优化。

 


http://chatgpt.dhexx.cn/article/ZtF4jvZp.shtml

相关文章

数据倾斜原理与解决方法

数据倾斜的概念 数据倾斜这四个字经常会在学习MapReduce中遇到。所谓数据分区,就是数据分区分布因为数据本身或者分区方法的原因变得极为不一致,大量的数据被划分到了同一个区。由于Reducer Task每次处理一个区的数据,这导致Reducer Task处理…

什么是缓存穿透、缓存雪崩、缓存击穿

缓存穿透 缓存穿透 :缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库,失去了缓存保护后端存储的意义。 解决方案 缓存空值 如果访问数据库后还未命中,则把一…

缓存穿透和缓存击穿

一、背景介绍 几乎所有互联网公司都采用缓存的方案来解决瞬时流量超高,或者长期流量过高的问题。但使用缓存存在风险——缓存穿透和缓存击穿:简单的讲就是如果该数据原本就不存在,那么就会发生缓存穿透;如果缓存内容因为各种原因…

缓存穿透,缓存雪崩,缓存击穿

一,缓存穿透 原因:一个请求来访问某个数据,发现缓存中没有,直接去DB中访问。此种情况就是穿透。(正常情况下缓存跟数据库中数据都是存在,异常情况下会导致) 特点:因传递了非法的key,导致缓存跟数据库中都无法查询 方…

如何避免缓存穿透、缓存击穿、缓存雪崩?

如何避免缓存穿透、缓存击穿、缓存雪崩? 缓存穿透 先来看一下缓存穿透,顾名思义,是指业务请求穿过了缓存层,落到持久化存储上。在大多数场景下,我们应用缓存是为了承载前端业务请求,缓存被击穿以后&#x…

缓存穿透、缓存击穿、缓存雪崩解决方案

微信搜索【程序员囧辉】,关注这个坚持分享技术干货的程序员。 前言 ​ 我一个QPS不到10的项目,天天问我缓存穿透、缓存击穿、缓存雪崩,我是真滴难。 可能大家经常会有这种感受,但是只要是面试要问的题目,就算用不上&…

缓存穿透 缓存击穿 缓存雪崩 这三者是什么 如何处理

通常我们使用缓存中间件的方式 将数据库的热点数据缓存到Redis中 尽量去缓存中查找数据,目的就是为了减轻数据库的压力 那什么是 缓存穿透,缓存击穿 与 缓存雪崩 呢 ? 缓存穿透 当Redis中不存在某个key时,将对数据库进行查询操作 但如果数据库也不存在 就会造成每一个请求即…

应对缓存击穿的解决方法

一.什么样的数据适合缓存? 分析一个数据是否适合缓存,我们要从访问频率、读写比例、数据一致性等要求去分析. 二.什么是缓存击穿 在高并发下,多线程同时查询同一个资源,如果缓存中没有这个资源,那么这些线程都会去数据库查找,对数据库造成极大压力,缓存失去存在的意义.打个…

redis缓存击穿

缓存击穿: 缓存击穿是指,针对某个访问非常频繁的热点数据的请求,无法在缓存中进行处理,紧接着,访问该数据的大量请求,一下子都发送到了后端数据库,导致了数据库压力激增,会影响数据…

【缓存】缓存穿透、缓存击穿、缓存雪崩及其解决方案

文章目录 缓存穿透缓存击穿缓存雪崩大量数据同时过期Redis 故障宕机 总结来源 用户的数据一般都是存储于数据库,数据库的数据是落在磁盘上的,磁盘的读写速度可以说是计算机里最慢的硬件了。 当用户的请求,都访问数据库的话,请求数…

Redis 缓存击穿,缓存穿透,缓存雪崩原因+解决方案

一、前言 在我们日常的开发中,无不都是使用数据库来进行数据的存储,由于一般的系统任务中通常不会存在高并发的情况,所以这样看起来并没有什么问题,可是一旦涉及大数据量的需求,比如一些商品抢购的情景,或者…

Redis缓存击穿、雪崩、穿透!(超详细)

缓存的击穿、穿透和雪崩应该是再熟悉不过的词了,也是面试常问的高频试题。 不过,对于这三大缓存的问题,有很多人背过了解决方案,却少有人能把思路给理清的。 而且,网络上仍然充斥着,大量不太靠谱的解决方案…

缓存穿透、缓存击穿、缓存雪崩如何应对

参考连接:redis避免缓存穿透为什么缓存空对象而不是null? - 知乎 缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的…

缓存穿透、缓存击穿、缓存雪崩区别和解决方案

一、缓存处理流程 前台请求,后台先从缓存中取数据,取到直接返回结果,取不到时从数据库中取,数据库取到更新缓存,并返回结果,数据库也没取到,那直接返回空结果。 二、缓存穿透 描述: …

缓存穿透,缓存雪崩,缓存击穿的超详解

文章目录 1、缓存穿透问题的解决思路2、缓存雪崩问题及解决思路3、缓存击穿问题及解决思路 1、缓存穿透问题的解决思路 缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库,失去了缓存的…

redis 缓存穿透,缓存击穿,缓存雪崩

虽然我们在使用 redis 缓存的时候非常的爽,它大大的提高了我们应用程序的性能和效率,尤其是数据查询方面,咱们不用直接去持久化的数据库中查询数据,而是到内存中查询数据即可 事物总是有两面的,用的爽的同时&#xff…

缓存穿透、缓存击穿、缓存雪崩的理解和解决方案

目录 一、缓存穿透 二、缓存击穿 三:缓存雪崩 在生产环境中,会因为很多的原因造成访问请求绕过了缓存,都需要访问数据库持久层,虽然对Redsi缓存服务器不会造成影响,但是数据库的负载就会增大,使缓存的作…

详解缓存穿透、缓存雪崩、缓存击穿

背景 在现代软件架构中,缓存的应用已经非常普及。缓存的使用在面试和实践中都是避不开的硬技能、硬知识,如果你说还不太熟悉缓存的使用,可能都不好意思说自己是程序员。 这篇文章,带大家进一步学习在缓存使用中不得不考虑三个特…

【Redis】缓存击穿问题及其解决方案

【Redis】缓存击穿问题及其解决方案 文章目录 【Redis】缓存击穿问题及其解决方案1. 缓存击穿概念2. 解决方案2.1 互斥锁2.1.1 互斥锁的优缺点2.1.2 互斥锁的代码实现 2.2 逻辑过期2.2.1 逻辑过期的优缺点2.2.2 逻辑过期的代码实现 1. 缓存击穿概念 缓存击穿:缓存击…

Redis 缓存穿透、缓存击穿、缓存雪崩

文章目录 一、缓存穿透1. 概念2. 解决方案 二、缓存击穿1. 概念2. 解决方案 三、缓存雪崩1. 概念2. 解决方案 一、缓存穿透 1. 概念 key 对应的数据在redis中并不存在,每次针对此 key的请求从缓存获取不到,请求转发到数据库,访问量大了可能…