我正在开发一个应用程序,以使用 Hadoop 框架处理(和合并)几个大型 Java 序列化对象(大小为 GB)。 Hadoop 存储将文件 block 分布在不同的主机上。但是由于反序列化将要求所有 block 都存在于单个主机上,因此它会极大地影响性能。与文本文件不同,我该如何处理不同 block 必须单独处理的情况?
最佳答案
有两个问题:一个是每个文件必须(在初始阶段)被整体处理:看到第一个字节的映射器必须处理该文件的所有其余部分。另一个问题是局部性:为了获得最佳效率,您希望每个此类文件的所有 block 都位于同一主机上。
整体处理文件:
一个简单的技巧是让第一阶段映射器处理一个文件名列表,而不是它们的内容。如果要运行 50 个 map 作业,请使用该部分文件名制作 50 个文件。这很简单,可以与 java 或流式 hadoop 一起使用。
或者,使用不可拆分的输入格式,例如 NonSplitableTextInputFormat
。
有关详细信息,请参阅 hadoop wiki 上的“How do I process files, one per map?”和“How do I get each of my maps to work on one complete input-file?”。
地区:
然而,这留下了一个问题,即您正在读取的 block 分布在整个 HDFS 中:通常是性能提升,这里是一个真正的问题。我不相信有任何方法可以将某些 block 链接起来在 HDFS 中一起移动。
是否可以将文件放在每个节点的本地存储中?这实际上是解决这个问题的最有效和最简单的方法:让每台机器启 Action 业来处理所有文件,例如/data/1/**/*.data
(尽可能聪明地高效使用本地分区和 CPU 内核数)。
如果文件源自 SAN 或 s3,请尝试直接从那里拉取:它是为处理集群而构建的。
关于使用第一个技巧的注意事项:如果某些文件比其他文件大得多,请将它们单独放在最早命名的列表中,以避免推测执行的问题。如果任务是可靠的并且您不希望某些批处理被多次处理,那么无论如何您都可以关闭此类作业的推测执行。
关于java - Hadoop:处理大型序列化对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3012121/