MapReduce 的过程详解

MapReduce shuffle过程详解! 目录一、MR的shuffle过程二、Map shuffle三、Reduce shuffle 一、MR的shuffle过程 MR的shuffle过程: input -> map -> shuffle -> reduce ->output MR的原理图: 二、Map shuffle 1.map()的数据会写入到内存(环形缓冲区:默认大小:100mb),当数据达到缓冲区总容量的80%(阈值)时,会将我们的数据spill到本地磁盘 1)分区(partitioner):分 阅读详情

mapreduce 过程如下图所示:



从整体上,mapreduce 框架可以分为五个不同实体:

1)客户端:提交 MapReduce job。

2)Yarn 资源管理器(resource manager):协调集群计算资源的分配

3)Yarn 节点管理器(node manager):启动和监视集群中每个节点的计算容器。

4)Mapreduce 应用管理器(application master):负责调度 mapreduce 任务。应用管理器和 MapReduce 任务是运行在容器中的,这个容器是由资源管理器分配的,并且接受阶段管理器的管理。

5) 分布式文件系统(通常为HDFS):用与上述不同实体之间文件的共享。


下面详细讲述mapreduce各个阶段的详细过程:

1 提交job

调用Job 对像的 submit() 方法将会创建一个JobSubmitter 实例,并且调用它的submitJobInternal()方法,进行job的提交。提交 job 以后, waitForCompletion()方法将每隔一秒钟 poll job 的运行状态,如果job的运行状态发生了改变则显示到控制台上。当job成功执行完毕,则会输出job 的统计细心,否则输出job出错的信息。

job 提交过程:

1)向 yarn 资源管理器申请一个新的 应用id(applicaiton id),用于唯一标示这个 mapreduce job。

2)检查job的输出路径是否合法。如果输出文件已经存在,则job不会提交,而是抛出异常,终止程序运行。

3)计算job的输入分片(input splits)。如果分片计算失败(比如输入文件不存在),则job不会被提交,抛出异常,程序终止。

4)将运行 job 需要的文件(job 的jar 包,配置文件和计算的输入分片)上传到共享文件系统(hdfs)的一个文件夹中(以这个job的 job ID 命名)。

5)调用资源管理器的 submitApplication() 方法,开始执行job。


2 job 初始化

当资源管理的submitApplication方法被调用时,资源管理器将请求转发给 Yarn 调度器。yarn 调度器分配出一个容器,资源管理器便在这个容器上启动应用管理器进程,容器的运行受节点管理器管理。

mapreduce 的应用管理器时一个java 程序,它的 main class 时 MRAppMaster。job初始化:它将会产生一些 bookkeeping 对像去跟踪job的运行状态,这些 bookkeeping对向接受task传来的运行报告。然后MRAppmaster 从 hdfs 上得到客户端计算的job的输入分片。MR 在每个输入分片上创建一个 map task,和一些 reduce task(由 mapreduce。job。reduces 属性决定或者 job对向的 setNumReduceTasks() 方法)。每个task都给一个ID。

应用管理器必须根据mapreduce去决定如何执行task。如果job很小,那么MR也许会选择在同一个jvm中完成它。这是因为申请容器和启动容器都是由花销的,并行计算带来的收益和花销相互抵消,反而不如在一个节点上执行的效率高

3 task 的分配

如果task在本地节点运行并不能带来好处,那么MR将会向资源管理器申请运行job的map 和 reduce 任务的容器。map 任务容器申请的优先级是高于reduce容器的,因为reduce必须等到map阶段全部都完成了才可以真正执行(除了reduce的准备阶段)。当map任务完成了5%,才开始申请reduce阶段需要的容器。

下面讲讲map 和 reduce 阶段容器的分配问题。运行reduce 任务的容器可以在节点上的任意节点,但是map容器的分配则要遵循一定条件。首先,尽可能在输入分片所在节点上分配容器,如果分配不了,则在和分片在同一个机架上的节点上分配容器,如果还是没有资源分配容器的话,那只好在任意机架上分配容器了,此时数据要跨越机架传递,效率不高。

容器申请请求还会指定运行task所需的内存和CPU资源。默认情况下,每个map和reduce任务分配1024M内存和一个虚拟核。每个job可以根据自身情况自由设置:mapreduce.map.memory.mb  、 mapreduce.reduce.memory.mb 、 mapreduce.map.cpu.vcores 、 mapreduce.reduce.cpu.vcores


4 任务执行

一旦一个task获得了资源管理器在指定节点上分配给它所需的内存和cpu资源,应用管理器则联系那个节点的节点管理器,然后启动该容器。任务是一个java应用,它的main class 是 YarnChild。在开始运行之前,它会从共享文件系统中获取它需要的资源,包括job配置文件、jar包,其他相关文件。获取了这些资源以后,便开始运行map或者reduce任务。

YarnChild 是运行在一个独立的jvm中,因此,用户定义的map和reduce函数在运行过程中产生的任何bug都不会影响到节点管理器的状态,比如导致节点管理器进程崩溃或者挂起。


5 运行过程和状态更新

mapreduce job往往都是比较耗时的,需要长时间运行的批处理程序,花费的时间从数十秒到数十小时,所以用户需要知道job运行在运行时候的状态。job和task都有状态:比如running、successfully、completed、failed。这小消息在job运行过程中不断发生变化,那么客户端如何知道这些呢?

当一个task在运行的时候,它会跟踪task运行的过程(task完成的比例)。比如map task,任务完成的比例是已被处理的输入数据的比例。对于reduce task则要复杂一点。它将reduce阶段分为三个部分,和shuffle三个阶段向对应。比如:reduce 阶段如果正在运行reduce函数,那么任务已经被完成5/6。

6 job 成功完成

当应用管理器收到通知:job的最后一个task已经完成了,那么它把job的状态改为 “successful”。然后在控制台输出job的统计信息。应用管理器和task容器清理工作环境。此时job的信息便可以在job 历史服务器里可以查询了。

7 job 失败

在真实环境中,job失败是很常见的。通常失败包括 1 task 失败 2 应用管理器失败  3 节点管理器失败  4 资源管理器失败。下面分别叙。

1)task 失败

当用户自定义的map 或者reduce task在运行过程中抛出异常,task jvm 会将异常上报到 应用管理器然后在退出。异常信息会被记入用户的日志。应用管理器将这个task标记为失败,并释放这个task占据的资源。

还有一种情况是task jvm 由于某种原因(也许是jvm自身bug导致的)突然终止了,但是没有来得及向应用管理器汇报,此时节点管理器会注意到,并将此异常上报到 应用管理器,应用管理器将这个task标记为失败。

还有一种情况,task进程被挂起了。如果应用管理器在一段时间内没有更新task的状态,则会被认为已经失败了。task 容器会自动被杀死。mapreduce.task.timeout 参数设置超时时间,默认是10分钟。

如果将超时时间设置为0,则不开启超时功能,这个适合于7*24小时的应用。

当一个task尝试运行失败,那么应用管理器会在另外一个节点上再次尝试执行。默认情况下,它最多尝试四次。这个次数是可以配置的。默认情况下,任何一个task失败了四次,则整个job被认为是失败的。

但是也可以设置失败的task比例不超过一定比例,则job依然可以继续执行。

一个task也可以被杀死,这个和失败是不一样的。

2)应用管理器失败

Mapreduce 的应用管理器失败了会再次尝试运行,默认会尝试运行两次。如果两次都失败则job运行失败。mapreduce.am.max-attempts 设置最多尝试次数。但是yarn资源管理器限制应用管理器最大的失败重启次数,每个应用都不能超过这个限制。yarn.resourcemanager.am.max-attempts ,默认是两次。

应用管理器失败重启机制:AM 会周期性向资源管理器发送心跳,如果资源管理器发现 AM 已经挂掉了,那么它会在一个新的容器中开启另一个AM实例。此时新的AM实例会利用job的历史服务器去恢复正在运行的 task 的状态,所以正在进行和已经完成的task不需要再次运行。如果不想让job继续执行,则可以关闭这个功能,让job重新执行:将 yarn.app.mapreduce.am.job.recovery.enable 设置为 false。

Mapreduce 客户端会向应用管理器询问job运行的状态。在job初始化时,MR 客户端会向资源管理器询问AM 的地址,客户端将这个信息缓存起来。如果AM 失败了,那么客户端请求将会超时,此时客户端会再次询问资源管理器 AM 的地址。

3) 节点管理器失败

如果一个节点管理器进程崩溃了,那么资源管理器将不会收到这个节点的心跳消息。默认情况下,如果资源管理器超过10分钟(yarn.resourcemanager.nm.liveness-monitor.expiry-interval-ms)没有收到节点管理器的心跳消息,则认为它已经挂了,然后将它从自己的列表中删除。

任何在这个失败的节点管理器上运行的task会恢复运行。

4)资源管理器失败

资源管理器的失败时很严重的。默认配置下,资源管理器存在单点故障,一旦失败,则所有job都不被恢复。

为了高可用,可以同时运行两个资源管理器,另一作为备用。如果活动的资源管理失败了,那么启用备用资源管理器,此时客户段不会收到严重影响。

客户端和节点管理器也要被配置成可以处理资源管理器失败的情况。因为此时可能有两个资源管理器。它们会尝试联系每一个资源管理直到发现活动的资源管理。如果活动的资源管理器失败了,那么它们会再次遍历连接的资源管理器,直到备用的资源管理变为活动状态。

8 mapreduce 的shuffle 和sort

mapreduce框架会保证每个reducer的输入数据都是按照key排好序的。从map的输出结果到这排序阶段就被成为ishuffle阶段,这个阶段时mapreduce阶段的精华也是难点,这部分的代码在每个版本中改动最多。

shuffle:将map输出结果送到reducer和排序的功能。

1) map:每个map task将结果输出到环形内存缓冲区,当到达一定阈值,则启动一个后台进程将缓存中的数据 1: 按照 reduce 阶段 reducer 的个数将数据分区,然后在每个分区里面的数据按照key键值排序,下一步,如果设置了 combiner 函数,则将这个combiner函数作用于上一步的结果,然后就是把数据保存到磁盘。
注意:
当这个后台进程将内存中的数据写入磁盘的时候,如果缓存已经满了,那么task会阻塞,直到spill阶段完成。
内存缓存默认是 100M,每当到达阈值则生成一个spill文件,task完成了以后,将多个spill文件合并成一个文件。这个文件是分区的,而且每个分区中的数据都是按key值排好序的。
可以让数据压缩
map 的数据是通过 http 传输给 reducer 的。
2)reduce:reducer 要执行任务,则第一步就需要获得 map 阶段输出到磁盘的数据。这个阶段叫做 copy phase。每个 reducer 默认有5个用于从远程机器获取数据的线程,并行执行。
  map task 完成以后会利用心跳机制通知 application master 。application master 知道 map 和 host 的对应关系。 每个reducer 有一个线程会周期性的询问 master map 阶段的输出数据位置,直到它已经获得所有map 阶段的数据为止。
copy phase:
1 如果 map 输出结果数据量比较小,则直接放在内存中,否则放到磁盘中。
2 当内存中的数据到达一定阈值,则将数据合并然后spill 到磁盘。(如果配置了 combiner , 那么保存到磁盘之前进行 combine)
3 copy 阶段继续执行,会开启一个后台进程将多个小文件合并并排序生成一个大文件。
4 当 map task 有一个完成了则开始 copy phase 
sorted phase:
当map阶段文件都已经copy到reducer段然后执行 sorted phase(merge phase)。
1 将各个 map 输出的文件合并。
reduce phase:
将 sorted 阶段的结果作为 reduce 函数的输入,输出结果,如果是hdfs文件,那么第一个block将保存在本地节点的机器上。
9 调优
调优的一般原则是:shuffle阶段的内存越大越好。
1)map reduce 函数占用的内存越少越好,尽量少用 Map 做聚合统计。
2)map 和 reduce task 占用的内存:mapred.child.java.opts,尽可能设置大点。
3)map 阶段的spill文件次数尽可能少


MapReduce shuffle过程详解 我们知道MapReduce计算模型主要由三个阶段构成:Map、shuffle、Reduce。Map是映射,负责数据的过滤分法,将原始数据转化为键值对;Reduce是合并,将具有相同key值的value进行处理后再输出新的键值对作为最终结果。为了让Reduce可以并行处理Map的结果,必须对Map的输出进行一定的排序与分割,然后再交给对应的Reduce,而这个将Map输出进行进一步整理并交给Reduc 阅读详情

相关推荐

MapReduce过程详解

MapReduce过程详解 数据运行的底层目前还是以hadoop为主,我们主要接触的还是上层抽象出来的比较方便的数据工具,例如hive,spark,impala等等,那么hadoop底层的核心原理又是什么呢? hadoop的底层核心由HDFS,MapReduce和YARN组成,HDFS是大数据的存储引擎,分布式文件系统,YARN是资源调度系统,而MapReduce就是它的计算框架,但同时,MapReduce也是一个编程模型,因为MapReduce抽象出来的框架,开发人员只需要按照其规则编写代码,就可以直

寻梦人 1902

MAPREDUCE的过程

mapreduce是hadoop的核心组件之一,主要是负责分布式计算的,它的核心思想就是“分而治之”。它的整个流程是什么样的呢,接下来我们就一步一步的介绍。 大致可以分为三个阶段:第一阶段是map阶段,第二阶段是shuffle阶段,第三阶段是reduce阶段。 其中第一阶段的map阶段分为两步: 第一步:首先通过InputFormat将文件读取进来,并进行切分,切分成(key,value)对的形式,key是该行数据的偏移量,value是这一行数据。切分完成后以(key,value)的形式发送给map端。 第

weixin_44658095的博客 5552

详解MapReduce全过程

我们为什么要如此大费周章的使用MapReduce?用MySQL处理不好吗?大家有没有这些疑问,明明很多的事情MySQL就能够解决的很好,为什么硬要上MapReduce呢?我来回答一下这个问题。MySQL是单机场景,而MapReduce是分布式系统,两个工具处理数据的能力是千差万别,mapreduce适合的是PB,TB级别的数据集处理,而mysql能力却较为有限。mapreduce采用分布式计算,容错性非常之高,一个节点报错了其他节点可以迅速进行补上。

2301_77702743的博客 2377

MapReduce的工作流程

Collect 阶段:在用户编写的 map() 函数中,数据处理完成后,一般会调用 outputCollector.collect() 输出结果,在该函数内部,它会将生成的 key / value 分片(通过调用 partitioner ),并写入一个环形内存缓冲区中(该缓冲区默认大小是 100MB )。Reduce 阶段:对排序后的键值对调用 reduce() 方法,键相等的键值对调用一次 reduce()方法,每次调用会产生零个或者多个键值对,最后把这些输出的键值对写入到 HDFS 中。

weixin_44901473的博客 2478

MapReduce 过程详解

MapReduce 过程详解一.Map端:二.Reduce端: 一.Map端: Map节点运行map task任务生成map的输出结果 1.Shuffer的工作内容 从运算效率的出发点,map的输出结果有限存储在map节点的内存中.每个map task都有一个内存缓冲区,存储着map的输出结果,当缓冲快满时,需要将缓冲区的数据以一个临时文件的形式存储到磁盘中,当整个map task结束后,在对磁盘中的这个临时文件做合并,生成最终的输出文件, 最后等待reduce task来拉取数据.当然当map t

ckw__xyy的博客 672

TI 实时操作系统SYS/BIOS使用总结

1:概述: SYS/BIOS 是一个可扩展的实时的操作系统。具有非常快速的响应时间(在中断和任务切换时达到较短的延迟),响应时间的确定性,强壮的抢占系统,优化的内存分配和堆栈管理(尽量少的消耗和碎片)。能够实现系统的模块化并可裁剪。 最大的特点就是:实时。 2:XDCtools: XDCtools 是SYS/BIOS引用的一种实时的软件组件技术(RTSC),它包括一些有用的工具,标准的AP

带头奋青的博客 5万+

map-reduce执行过程

使用过滤器来过滤掉不必要的数据。使用压缩算法来压缩数据。使用合并分组来减少分组数。使用 Hadoop 的 DistributedCache 机制来缓存常用的数据。使用 Apache Spark 等更高效的计算框架来替代 MapReduce。总体而言,Shuffle 是 MapReduce 中的关键环节,它决定了 MapReduce 的性能。通过优化 Shuffle,可以提高 MapReduce 的性能。

xxx 1362

stm32 + freertos + c++混合编程方法

其他一些资料上面,c++配置成--cpp11或者-cpp 都是把工程配置成c++。三、添加cpp文件,我们调用cpp文件里面的接口函数,不需要修改main.c后缀名。2、配置工程编译时候是--c99,是因为工程里面FreeRTOS是c语言,c++模式会报错。我们这里是默认c,编写的c++文件,单独选择--cpp编译,这在后面配置!c++是面向对象编程,对于一些项目来说,c++编程更加合适!stm32cubemax配置,这里就不写了,配置资料比较多。这里就是让cpp文件在c++下编译。最后,编程成功,点亮!

yuhu0012的博客 2629

MapReduce工作机制总结

总结从MapReduce程序中的JobClient.runJob(conf)开始,给出了MapReduce执行的流程图(如下),并分析了流程图中的四个核心实体,结合实际代码介绍了MapReduce执行的详细流程。 MapReduce的执行流程简单概括如下: 用户作业执行JobClient.runJob(conf)代码会在Hadoop集群上将其启动。 启动之后...

summerhai 307

STM32 热敏电阻测量温度

1、硬件 STM32F103C8T6、热敏电阻传感器、OLED。 2、热敏电阻传感器的介绍

weixin_54721788的博客 1万+

【AutoSAR】【WdgM】WdgM安全管理模块

一、WdgM在AutoSAR里的整体架构 WdgM是在autosar架构里位于服务层的一个基础软件模块;主要监督程序的执行; 主要包括三个模块: 看门狗管理器(WdgM) 看门狗接口(WdgIf) 看门狗驱动(Wdg) 二、三种监督机制 Alive监控-------主要监控周期性软件程序的时间 DeadLine监控-------主要监控非周期软件程序 程序流监控-------主要监控程序流执行的正确性 三、基于全局状态的检测流程 受监管实体(SE):Supervised Ent

专注汽车软件开发、AutoSAR、车载以太网、SOA、EE架构。 2990

深入学习Hadoop之第二篇——MapReduce

概念:MapReduce是一种数据处理的编程模型 一、Map 1.数据流: 一个MapReduce job是客户端所执行的work的单元,它包括:输入数据、MapReduce程序以及配置信息; Hadoop把MapReduce job分割为更小的tasks(map tasks和reduce tasks)来执行,这些tasks被YARN调度在集群节点上执行;如果一个task失败了,它

每天进步一点点... 591

斗鱼直播间弹幕爬虫实战:WebSocket连接与实时数据采集

在数据驱动的时代,直播平台的弹幕数据蕴含着巨大的价值——用户行为分析、舆情监控、弹幕情感分析、直播热度评估等应用场景层出不穷。斗鱼作为国内领先的直播平台,其弹幕系统基于WebSocket协议实现实时双向通信。本文将带您从零开始,使用Python构建一个完整的斗鱼直播间弹幕爬虫系统。

2201_76125261的博客 134

MapReduce的shuffle过程详解

Shuffle过程是MapReduce框架中不可或缺的一部分,它确保了Map阶段输出的数据能够有序、高效地传递给Reduce阶段。通过对Shuffle过程的深入了解和优化,可以显著提升MapReduce作业的性能。版权声明:本博客内容为原创,转载请保留原文链接及作者信息。参考文章MapReduce Shuffle源码解读MapReduce的Shuffle过程的七大操作。

ning的博客 1821

AI人工智能领域多模态数据融合在智能诊断系统的应用案例

在医疗诊断领域,单一模态数据(如CT影像或电子病历)的局限性日益凸显——就像老中医只"望"不"闻"会漏掉关键线索。本文将深入解析多模态数据融合技术如何突破这一瓶颈:从生活化的"中医四诊"类比切入,拆解数据层/特征层/决策层融合的技术原理;结合肺癌智能诊断的真实案例,展示CT影像、病理文本、基因数据、生命体征的多模态融合全流程;最后探讨技术落地的核心挑战与未来方向。无论你是医疗从业者、AI开发者,还是对智能诊断感兴趣的爱好者,都能从中获得技术启发与应用思路。

AGI×大数据,开启智能时代的认知跃迁;解码AGI,赋能数据驱动的智能革命。 832

80、编程学习资源与x86知识全解析

本文详细介绍了编程学习中多个领域的优秀书籍和博客资源,涵盖逆向工程、C/C++、x86/x86-64架构、ARM、汇编语言、Java、UNIX、密码学等多个方向。同时,深入解析了x86架构的核心知识,包括术语、通用寄存器、FPU寄存器、SIMD寄存器、调试寄存器以及常用指令的使用方法和操作步骤。通过本文,读者可以系统地掌握底层编程知识,并应用于逆向工程、系统开发和性能优化等领域。

tree的博客 219

详解MapReduce过程

一.MapReduce工作流程图片如下 二.工作流程机制详解 1.TextInputFormat读取文件详细解析 追踪源代码后,我们会发现TextInputFormat这个类继承自FileInputFormat,而FileInputFormat这个类继承自InputFormat 查看InputFormat的源码注释我们了解到这个类的作用为: 1.验证作业的输入规格 2.将输入文件分成逻辑块(默认大小等于block的大小(通常为128M)),然后将每个逻辑文件分配给一个单独的Mapper 3.提供Reco

sun_0128的博客 8057

STM32实战开发(110):基于STM32的智能地震监测系统开发

地震监测系统是自然灾害预警体系中至关重要的一部分。随着地震灾害的频发和对自然灾害预测精度要求的提高,智能地震监测系统逐渐成为研究的热点。STM32作为一款高性能的微控制器,凭借其强大的处理能力和丰富的外设接口,在地震监测领域中得到了广泛应用。本篇文章将详细介绍如何使用STM32实现一个智能地震监测系统的开发过程,涵盖硬件设计、软件编程、系统实现及相关代码。通过集成加速度传感器、地震数据采集、实时数据处理和无线数据传输功能,我们可以设计一个高效、稳定的智能地震监测系统。

2201_76125393的博客 710

MapReduce过程详解(非常全)

MapReduce算法执行过程 (1)MapReduce框架使用InputFormat模块做Map前的预处理,比如验证输入的格式是否符合输入定义;然后,将输入的文件切分为逻辑上的多个InputSplit,InputSplit是MapReduce对文件进行处理和运算的实际单位(逻辑概念),每个InputSplit没有对文件进行实际切割,只是记录了要处理的数据的位置和长度。 (2)InputSplit是逻辑切分,所以需要通过RecordReader(RR)根据InputSplit的信息来处理InputSplit

qq_45725767的博客 7880

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Mapreduce执行过程详解

一、分析MapReduce执行过程 MapReduce运行的时候,会通过Mapper运行的任务读取HDFS中的数据文件,然后调用自己的方法,处理数据,最后输出。Reducer任务会接收Mapper任务输出的数据,作为自己的输入数据,调用自己的方法,最后输出到HDFS的文件中。整个流程如图: 二、Mapper任务的执行过程详解 每个Mapper任务是一个java进程,它会读...

yangshaojun1992的博客 3万+

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

MapReduce排序过程详解

Hadoop、Spark等分布式数据处理框架在宣传自己的性能时大都以排序效果来做比较,各种类别的Sort Benchmark已成为行业基准测试。之所以选择排序是因为排序的核心是shuffle操作,数据的传输会横跨集群中所有主机,Shuffle基本支持了所有的分布式数据处理负载。 下面就来详细分析一下使用mapreduce实现排序的基本过程。先看一些准备知识。 MapReduce中的数据

zr459927180的博客 1万+

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

MapReduce Shuffle 过程详解

MapReduce Shuffle 过程详解 一、回顾 Shuffle功能 分区 问题:MapReduce中Reduce的设计本身是为了实现聚合,所以Reduce进程默认只会启动一个 单个ReduceTask如果处理的数据量过多,会导致性能较差,或者资源不足导致程序运行失败 功能:每个分区就是一个ReduceTask进程,允许启动配置多个分区,多个ReduceTask 通过多个分区来并行处理数据,通过分布式Reduce过程来解决资源和性能问题 应用:判断ReduceTask处理的

qq_43528451的博客 801
上一篇: hadoop map reduce 阶段笔记
下一篇: MapReduce 调优基本思路
touch_future
博客等级 码龄10年 3粉丝 12原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值