我对 InputSampler 的理解是它从记录读取器和采样键中获取数据,然后在 HDFS 中创建一个分区文件。
我对这个采样器有几个疑问:1)这个采样任务是地图任务吗?2)我的数据在 HDFS 上(分布在我的集群的节点上)。这个采样器会在有数据被采样的节点上运行吗?3) 这会消耗我的地图位置吗?4) 示例会与我的 MR 作业的地图任务同时运行吗?我想知道它是否会通过减少槽数来影响映射器消耗的时间?
我对 InputSampler 的理解是它从记录读取器和采样键中获取数据,然后在 HDFS 中创建一个分区文件。
我对这个采样器有几个疑问:1)这个采样任务是地图任务吗?2)我的数据在 HDFS 上(分布在我的集群的节点上)。这个采样器会在有数据被采样的节点上运行吗?3) 这会消耗我的地图位置吗?4) 示例会与我的 MR 作业的地图任务同时运行吗?我想知道它是否会通过减少槽数来影响映射器消耗的时间?
我发现 InputSampler 做了一个有严重缺陷的假设,因此不是很有帮助。
这个想法是它从映射器输入中采样键值,然后使用结果统计信息来均匀地划分映射器输出。然后假设映射器输入和输出的键类型和值分布相同。以我的经验,映射器几乎从不会在读取时向减速器发送相同的键值类型。所以 InputSampler 是无用的。
在几次为了有效分区而必须进行采样的情况下,我最终将采样作为映射器的一部分进行(因为直到那时我才知道正在生成哪些键)并将结果写入映射器的 close()方法到目录(每个映射器一组统计信息)。然后,我的分区器必须在第一次调用时执行延迟初始化,以读取映射器编写的文件,将统计信息吸收到一些有用的结构中,然后相应地对后续键进行分区。
您唯一的其他真正选择是在开发时猜测键值是如何分布的,并将该假设硬编码到您的分区器中。
不是很干净,但这是我能想到的最好的。
这个问题很久以前就问过了,很多问题都没有回答。
@Chris 唯一且投票最多的答案并没有真正回答问题,而是给出了一个有趣的观点,尽管在我看来有点过于悲观和误导,所以我也会在这里讨论它。
采样任务在对 的调用中完成InputSampler.writePartitionFile(job, sampler)
。对该方法的调用是阻塞的,在此期间采样完成,在同一个线程中。
这就是为什么您不需要调用job.waitForCompletion()
. 它不是 MapReduce 作业,它只是在您的客户端进程中运行。此外,一个 MapReduce 作业至少需要 20 秒才能开始,但对一个小文件进行采样只需要几秒钟。
因此,您所有问题的答案都是“否”。
如果您查看 的代码writePartitionFile()
,您会发现它调用sampler.getSample()
,谁将调用inputformat.getSplits()
以获取所有输入拆分的列表作为样本。
然后将顺序读取这些输入格式以提取样本。每个输入拆分都由在同一方法中创建的新记录读取器读取。这意味着您的客户正在阅读和采样。
您的其他节点没有运行任何“映射”或其他进程,它们只是为 HDFS 提供您的客户端所需的块数据,以便进行采样所需的输入拆分。
现在,讨论克里斯给出的答案。我同意 InputSampler 和 TotalOrderPartitioner 在某些方面可能存在缺陷,因为它们确实不容易理解和使用......但它们并没有强制地图输入和输出之间的键类型相同。
InputSampler 使用作业的 InputFormat(及其 RecordReader)键来创建包含所有采样键的分区文件。然后,TotalOrderPartitioner 在 Mapper 进程结束时的分区阶段使用此文件来创建分区。
最简单的解决方案是为 InputSampler 创建一个自定义 RecordReader,它执行与Mapper相同的键转换。
为了说明这一点,假设您的数据集包含成对的 (char, int),并且您的映射器通过获取字符的 ascii 值将它们转换为 (int, int)。例如,“a”变为 97。
如果您想对该作业执行全顺序分区,您的 InputSampler 将对字母“a”、“b”、“c”进行采样。然后在分区阶段,您的映射器输出键将是整数值,如 102 或 107,与分区文件中用于分区分配的 'a'、'g' 或 't' 不可比较。这是不一致的,这就是为什么在使用相同的 InputFormat 进行采样和 mapreduce 作业时,输入和输出键类型被假定为相同的原因。
因此解决方案是编写一个自定义 InputFormat 及其 RecordReader,仅用于采样客户端作业,它读取您的输入文件并在返回每条记录之前执行相同的char
转换int
。这样,InputSampler 将直接将来自自定义记录读取器的整数 ascii 值写入分区文件,该分区文件保持相同的分布,并且可用于映射器的输出。
几行文字解释文本并不容易掌握,但任何有兴趣完全了解 InputSampler 和 TotalOrderPartitioner 如何工作的人都应该查看此页面:http ://blog.ditullio.fr/2016/01/04/hadoop -basics-total-order-sorting-mapreduce/
它详细解释了如何在不同的情况下使用它们。