本文為您介紹在使用MapReduce時的常見問題。
問題類別 | 常見問題 |
功能咨詢 | |
開發MapReduce | |
常見報錯 |
MapReduce的輸入源可以是視圖嗎?
不可以,只能是表。
MapReduce的結果寫入到表或分區時,會覆蓋還是追加數據?
會覆蓋掉原有的表數據或分區數據。
MapReduce中是否可以調用Shell文件?
不可以,受Java沙箱限制。更多Java沙箱信息,請參見Java沙箱。
reduce.setup能否讀入輸入表?
不能讀入輸入表,只能讀入緩存表。
Mapper是否支持同一表格多分區輸入?
Mapper支持同一表格多分區輸入,同一張表的多個分區可以理解為獨立的兩張表。
Mapper可以直接從Record中讀取分區數據段的信息嗎?
Mapper無法從Record中獲取分區字段信息,但是可以使用如下代碼。PartitionSpec為分區信息。
PartitionSpec ps = context.getInputTableInfo().getPartitionSpec();
String area = ps.get(“area”);
Label和分區是什么關系?
Label是給不同的輸出處打上的一個標簽,當輸出的時候可以識別是從哪里輸出的。
MapReduce中是否可以只有Map?
可以,MapReduce支持Map-Only。如果是Map-Only作業,需要顯式指定Reducer數量為0,即job.setNumReduceTasks(0)
。
Mapper中輸入表中的每條Record數據,是否可以按列名讀取?
可以。輸入表中的每條Record數據不僅可以按序號record.get(i)
讀取,還可以按照列名來獲取Record,例如record.get("size")
。
write(Record key, Record value)
與write(Record record)
的區別是什么?
write(Record key, Record value)
:輸出中間結果,例如key.set(“id”, v1),value.set(“size”, v2)
。Map產出的中間結果,需要網絡傳輸給Reduce,沒有關聯表進行類型推斷,所以必須聲明字段類型用于序列化。輸出的字段類型是MaxCompute的字段類型。job.setMapOutputKeySchema(SchemaUtils.fromString(“id:string”)); job.setMapOutputValueSchema(SchemaUtils.fromString(“size:bigint”));
write(Record record)
:輸出結果到最終表,有表進行類型推斷,沒必要聲明字段類型。
MaxCompute MapReduce中,為什么要指定兩個JAR,Libjars和Classpath?
本地客戶端會執行一些作業配置等操作,涉及遠程執行。因此本地有一個執行器,遠程有一個執行器。
遠程執行器執行加載遠程的Classpath,即-libjars mapreduce-examples.jar
。本地執行器加載本地Classpath,所以也要指定-classpath lib/mapreduce-examples.jar
。
Hadoop MapReduce的源碼,能否直接應用于MaxCompute MapReduce?
不能。MaxCompute MapReduce與Hadoop MapReduce API有一定差別,但整體風格一致。您需要修改Hadoop的源碼,并在MaxCompute MapReduce SDK下編譯通過后,才能在MaxCompute上運行。
MapReduce如何實現排序?
排序代碼如下。
//設置排序的字段(這里根據i1,i2兩個字段進行排序)。
job.setOutputKeySortColumns(new String[] { "i1", "i2" });
//設置字段的排序順序(這里設置i1為正序排序,i2為逆序排序)。
job.setOutputKeySortOrder(new SortOrder[] { SortOrder.ASC, SortOrder.DESC });
setOutputKeySortOrder方法的用法,如下所示。
public void setOutputKeySortOrder(JobConf.SortOrder[] order)
功能:設置Key排序列的順序。
參數: Order表示排序列的順序。可選值為ASC(升序)、DESC(降序)。
MapReduce中的Backups是什么?
Backups就是一種加速調優。MaxCompute會查看您的任務,如果存在一些任務的工作量特別大,便為其開啟備份任務,兩個任務執行一樣的數據,結果用最先執行結束的任務,因此存在Backups。但是如果任務非常大,Backups也無法起作用,因為原本的任務和Backups都沒有執行完成。
開發MapReduce時,如何在命令行傳入多個資源?
用逗號(,)分隔符進行分隔,例如輸入命令jar -resource resource1,resource2,..
即可。
在Main方法中如何判斷一個表為空表?
您可以使用如下方式判斷一個表是否為空表。
Odps odps=SessionState.get().getOdps();
Table table=odps.tables().get('tableName');
RecordReader recordReader=table.read(1);
if(recordReader.read()==null){
//TO DO
在MaxCompute MapReduce中,如何設置Java代碼,才能打印出日志?
推薦如下方法:
可以在代碼中用
System.out.println
打印日志,對應日志輸出位置是在Logview的stdout中。使用出現異常時,客戶端會返回異常信息,不需要打印日志信息。
使用common logging,日志輸出到stderr中,可以在Logview的stderr看到。
結果表中會保留兩個MapReduce計算之后的重復數據嗎?
會。查詢數據時,會得到兩條一樣的數據。
Hadoop中可以選擇多個Node進行分布處理(一個Node表示一臺機器),那么MaxCompute MapReduce進行分布處理時,該如何設置Node?
您不需要自行搭建分配Node,這正是MaxCompute的優點之一。
當運行MapReduce時,MaxCompute底層會根據算法決定使用的數據分片。
不使用Combiner時輸出正常,使用Combiner后Reduce沒有輸入,是什么原因?
Reduce輸出的單個Record和Map輸出的Key-Value對不一致,導致產生上述情況。
在MapOnly中,為什么程序沒有指定輸出Table的Schema格式?
輸出表的Schema是需要預先創建好的,在create table
的時候指定。MapOnly程序內部不用指定Schema,可以直接輸出。
如何在本地調用MaxCompute服務器運行MapReduce任務?
正常情況下,MaxCompute的JAR包需要在命令行工具上執行jar
命令來執行,具體語法請參見MapReduce作業提交。
您也可以通過模擬的方式整合到自己的工程中,方法如下:
設置包依賴。
除了基本的SDK,還需要其他的幾個依賴包,您可在客戶端工具的lib文件夾中找到。lib文件夾中也包含了SDK的JAR包,建議您在導入包的時候把最新的客戶端工具lib文件夾中的JAR包全部導進來。
上傳JAR包。
將在本地測試通過的MapReduce程序,打成JAR包并上傳,假設此JAR包的名稱是mr.jar。更多上傳資源操作,請參見資源操作。
設置運行方式。
配置Jobconf,配置示例如下。
//配置MaxCompute連接信息。 Account account = new AliyunAccount(accessid, accesskey); Odps odps = new Odps(account); odps.setEndpoint(endpoint); odps.setDefaultProject(project); //獲取session。 SessionState ss = SessionState.get(); ss.setOdps(odps); ss.setLocalRun(false); //設置false,表示在服務器上跑。如果要在本地調試,直接設置為true。 //正常的設置jobconf等代碼。 Job job = new Job(); String resource = “mr.jar”; job.setResources(resource); //這一步類似Jar命令的jar -resources mr.jar。 //后面的代碼為正常的MapReduce代碼規則。 job.setMapperClass(XXXMapper.class); job.setReducerClass(XXXReducer.class);
配置完成之后,您可以直接運行MapReduce任務。
執行MaxCompute MapReduce時,報錯BufferOverflowException,如何解決?
問題現象
執行MaxCompute MapReduce時,返回如下報錯。
FAILED: ODPS-0123131:User defined function exception - Traceback: java.nio.BufferOverflowException at java.nio.DirectByteBuffer.put(Unknown Source) at com.aliyun.odps.udf.impl.batch.TextBinary.put(TextBinary.java:35)
產生原因
一次寫入的數據太大,導致Buffer溢出。
解決措施
MaxCompute的單個字段可以寫入的數據類型限制如下。
String 8MB Bigint -9223372036854775807 ~ 9223372036854775807 Boolean True/False Double -1.0 10308 ~ 1.0 10308 Date 0001-01-01 00:00:00 ~ 9999-12-31 23:59:59
執行MaxCompute MapReduce時,報錯Resource not found,如何解決?
提交作業時,要用-resources
指定需要的資源,多個資源用逗號(,)分隔。
執行MaxCompute MapReduce時,報錯Class Not Found,如何解決?
執行MapReduce時,以下兩種情況會報此錯誤:
classpath
參數的類名寫錯,要寫上完整的包名。打包JAR的時候出錯,注意打包時要把SRC中的源碼都選上。
執行MaxCompute MapReduce時,報錯ODPS-0010000,如何解決?
問題現象:
執行MaxCompute MapReduce時,返回如下報錯。
ODPS-0010000: System internal error - get input pangu dir meta fail.
產生原因
出現上述報錯,是因為您還未創建分區,或是因為分區數據未到位,您就開始使用此分區。
解決措施
先創建分區,然后再運行MapReduce任務。
執行MaxCompute MapReduce時,報錯Table not found,如何解決?
問題現象:
執行MaxCompute MapReduce時,返回報錯如下。
Exception in thread "main" com.aliyun.odps.OdpsException: Table not found: project_name.table_name.
產生原因
目標項目不正確或目標表不存在。
解決措施
MapReduce接口的Table Info Builder是ProjectName和TableName,兩個接口分別設置為Project名稱和Table名稱。
執行MaxCompute MapReduce時,報錯ODPS-0123144,如何解決?
問題現象:
執行MaxCompute MapReduce時,返回報錯如下。
FAILED: ODPS-0123144: Fuxi job failed - WorkerRestar
產生原因:
出現上述報錯,是因為集群的備節點在計算的過程中出現超時的情況,導致主節點認為備節點故障,所以報錯。超時10分鐘,即會報錯,暫時不支持用戶自行配置。
解決措施
這個報錯比較常見的原因是Reduce里做了大循環,例如存在長尾數據或者笛卡爾積。您需要盡量減少這種大循環的情況。
執行MaxCompute MapReduce時,報錯java.security.AccessControlException,如何解決?
問題現象
執行MaxCompute MapReduce時,返回報錯如下。
FAILED: ODPS-0123131:User defined function exception - Traceback: java.lang.ExceptionInInitializerError ... Caused by: java.security.AccessControlException: access denied ("java.lang.RuntimePermission" "getProtectionDomain") at java.security.AccessControlContext.checkPermission(AccessControlContext.java:472)
產生原因
出現上述報錯,是因為您的代碼違反了沙箱限制,詳情請參見Java沙箱。
解決措施
您需要訪問外部的資源解決此報錯。但MaxCompute目前不支持訪問外部資源,請將外部的處理邏輯和涉及的數據存儲在MaxCompute上進行訪問。您需要讀取一些配置文件,詳情請參見使用資源示例。
執行MaxCompute MapReduce時,報錯 java.io.IOException,如何解決?
問題現象:
執行MaxCompute MapReduce時,返回報錯如下。
Exception in thread “main“ java.io.IOException: ODPS-0740001: Too many local-run maps: 101, must be <= 100(specified by local-run parameter ‘odps.mapred.local.map.max.tasks‘)
產生原因
local-run maps默認是100,需要調整。
解決措施
您可以添加
-Dodps.mapred.local.map.max.tasks=200
配置。
執行MaxCompute MapReduce時,報錯Exceed maximum read times,如何解決?
問題現象:
執行MaxCompute MapReduce時,返回報錯如下。
ODPS-0730001: Exceed maximum read times per resource
產生原因:
資源文件讀取的次數太多。
解決措施
請檢查代碼中讀取對應資源的代碼邏輯。一般情況下,資源讀取在setup中執行一次即可,不要在Map或Reduce階段中多次讀取。
執行MaxCompute MapReduce時,Reduce還沒開始執行第一句,便報錯為內存溢出,如何解決?
產生原因
某些數據特別大,下載到內存便溢出了。
解決措施
把Combiner去掉或者在Combiner中限制Size
set odps.mapred.map.min.split.size=512;
。
執行MaxCompute MapReduce時,報錯內存溢出,如何解決?
內存溢出通常是由于內存不足導致的,可以通過調整JVM內存參數(odps.stage.mapper.jvm.mem和odps.stage.reducer.jvm.mem
)解決。例如set odps.stage.mapper.jvm.mem = 2048
將內存調整為2 GB。
執行MaxCompute MapReduce時,開啟了600個Reducer加載一個配置文件,但是配置文件很小且報錯java.lang.OutOfMemoryError,如何解決?
執行MaxCompute MapReduce時,報錯ODPS-0420095,如何解決?
問題現象
執行MaxCompute MapReduce時,返回報錯如下。
Exception in thread "main" java.io.IOException: com.aliyun.odps.OdpsException: ODPS-0420095: Access Denied - The task is not in release range: LOT
產生原因
項目為MaxCompute開發者版資源下的項目,僅支持MaxCompute SQL(支持使用UDF)、PyODPS作業任務,暫不支持MapReduce、Spark等其它任務。
解決措施
升級項目規格,請參見轉換計費方式。
在MapReduce中使用資源時,報錯文件太多,如何解決?
問題現象
在MapReduce中使用資源時,返回報錯如下。
Caused by: com.aliyun.odps.OdpsException: java.io.FileNotFoundException: temp/mr_XXXXXX/resource/meta.user.group.config (Too many open files)
產生原因
單個作業引用的資源數量不能超過256個,否則報錯。Table和Archive按照一個單位計算。更多限制請參見使用限制。
解決措施
調整引用的資源數量。
在MapReduce程序中使用第三方類,打了一個Assembly的JAR包,運行時報錯找不到類,如何解決?
MaxCompute MapReduce在分布式環境中運行時受到Java沙箱的限制(MapReduce作業的主程序則不受此限制),具體限制請參見Java沙箱。
如果您只是需要處理Json,建議您直接使用Gson,同時無需打包帶Gson的Class。Java開源組件里提供了很多字符串轉日期的方法,例如SimpleDateFormat等。
使用開源兼容MapReduce在MaxCompute上運行時,報錯顯示下標越界,如何解決?
建議您使用MaxCompute的MapReduce接口進行代碼編寫。同時,非必須場景下建議使用Spark替代MapReduce。