Esta página responde às perguntas mais frequentes sobre o MaxCompute MapReduce, organizadas em três categorias.
|
Categoria |
Perguntas |
|
Fontes de entrada, modo de gravação, comportamento da API, ordenação, backups |
|
|
Recursos, logs, execução local, configuração de nós |
|
|
OOM, BufferOverflowException, Class Not Found, entre outros |
Antes de solucionar problemas
Se um job falhar, verifique primeiro a mensagem de erro e o Logview:
stdout no Logview: saída gerada por
System.out.printlnno código do mapper ou reducer.stderr no Logview: saída gerada por frameworks de log padrão.
Saída do cliente MaxCompute: em muitas falhas de job, o cliente exibe os detalhes do erro diretamente, dispensando a consulta aos logs para diagnóstico.
Recursos
Posso usar views como fontes de entrada?
Não. Jobs MapReduce aceitam apenas tabelas como fontes de entrada, não views.
Em qual modo os resultados são gravados em uma tabela ou partição?
Os resultados são gravados no modo de sobrescrita.
Posso executar um job MapReduce chamando arquivos shell?
Não. As restrições do sandbox Java impedem que jobs MapReduce chamem arquivos shell. Para obter detalhes sobre as restrições do sandbox, consulte Sandbox Java.
O método setup() do reducer pode ler tabelas de entrada?
Não, mas ele pode ler tabelas em cache. O método setup() de um reducer não acessa tabelas de entrada diretamente.
Um mapper aceita múltiplas partições como entrada?
Sim. Um mapper pode receber dados de várias partições da mesma tabela. Cada partição é tratada como uma tabela separada.
Um mapper pode ler campos de partição dos registros de dados?
Não. Os campos de partição não estão incluídos nos registros de dados. Use context.getInputTableInfo().getPartitionSpec() em vez disso:
PartitionSpec ps = context.getInputTableInfo().getPartitionSpec();
String area = ps.get("area");
Qual é a relação entre rótulos e partições?
Os rótulos identificam as partições nas quais os dados de saída são gravados.
O MaxCompute MapReduce suporta jobs map-only?
Sim. Defina o número de reducers como 0:
job.setNumReduceTasks(0);
Um mapper pode ler registros pelo nome da coluna?
Sim. É possível acessar registros por índice (record.get(i)) ou pelo nome da coluna (record.get("size")).
Quais são as diferenças entre write(Record key, Record value) e write(Record record)?
write(Record key, Record value) gera resultados intermediários que um mapper transmite a um reducer pela rede. Como nenhum schema de tabela de saída está disponível nessa etapa, declare os tipos de dados dos campos explicitamente:
job.setMapOutputKeySchema(SchemaUtils.fromString("id:string"));
job.setMapOutputValueSchema(SchemaUtils.fromString("size:bigint"));
Já write(Record record) grava os resultados finais diretamente em uma tabela de saída. O schema da tabela está disponível, portanto os tipos de dados são inferidos automaticamente — nenhuma declaração explícita é necessária.
Por que preciso de -libjars e -classpath ao enviar um job MapReduce?
Dois executores estão envolvidos: um executor local (seu cliente MaxCompute) e um executor remoto (o cluster MaxCompute).
-classpathespecifica o JAR para o executor local — por exemplo,-classpath lib/mapreduce-examples.jar.-libjarsespecifica o JAR para o executor remoto — por exemplo,-libjars mapreduce-examples.jar.
Ambos são necessários porque o cliente realiza operações locais (como configuração do job), enquanto o cluster executa a computação efetiva.
Posso usar o código-fonte do Hadoop MapReduce diretamente no MaxCompute?
Não. Embora o estilo geral de programação seja semelhante, a API do MaxCompute MapReduce difere da API do Hadoop MapReduce. Para executar código do Hadoop MapReduce no MaxCompute, reescreva-o utilizando o SDK do MaxCompute MapReduce.
Como ordenar dados com o MaxCompute MapReduce?
Especifique as colunas de ordenação e a ordem na configuração do seu job:
// Sort by i1 (ascending) and i2 (descending)
job.setOutputKeySortColumns(new String[] { "i1", "i2" });
job.setOutputKeySortOrder(new SortOrder[] { SortOrder.ASC, SortOrder.DESC });
setOutputKeySortOrder aceita um array de valores SortOrder. Os valores válidos são ASC (ascendente) e DESC (descendente), um para cada coluna de ordenação.
O que são backups para jobs MapReduce?
O MaxCompute monitora o progresso do job. Quando um job precisa processar um grande volume de dados, o MaxCompute inicia automaticamente um job de backup que processa os mesmos dados em paralelo. O resultado do job que terminar primeiro é utilizado, e o outro é descartado. Se o volume de dados for extremamente grande, tanto o job original quanto o de backup podem exceder o limite de tempo — nesse caso, os backups não melhoram o desempenho.
Desenvolvimento de programas
Como passar múltiplos recursos ao enviar um job MapReduce?
Separe os nomes dos recursos com vírgulas:
jar -resource resource1,resource2,resource3
Como verificar se uma tabela está vazia no método main?
Odps odps = SessionState.get().getOdps();
Table table = odps.tables().get("tableName");
RecordReader recordReader = table.read(1);
if (recordReader.read() == null) {
// Table is empty
}
Como gerar logs para um job MapReduce?
Use System.out.println no seu código — a saída vai para stdout no Logview. Se você utilizar um framework de log padrão, os logs vão para stderr no Logview.
Se um job falhar, o cliente MaxCompute também exibe os detalhes do erro diretamente, portanto os logs geralmente não são necessários para o diagnóstico de erros.
Uma tabela de resultados acumula dados duplicados entre dois jobs MapReduce?
Sim. Se dois jobs MapReduce distintos gravarem na mesma tabela de resultados, a tabela conterá registros duplicados — um de cada job. Consultas nessa tabela retornarão ambas as cópias.
Preciso configurar nós para processamento distribuído no MaxCompute?
Não. O MaxCompute gerencia a alocação de shards automaticamente. Diferentemente do Hadoop MapReduce, não há configuração de nós — o runtime do MaxCompute determina quais shards cada job utiliza com base em seu algoritmo interno.
Após adicionar um combiner, os reducers não recebem entrada. Por quê?
Esse problema ocorre porque cada registro gerado por um reducer não pode ser mapeado para os pares chave-valor gerados por um mapper. Verifique se o schema de saída do combiner corresponde ao schema de saída do mapper.
Por que não consigo especificar o schema da tabela de saída ao executar um job map-only?
O schema é fixado no momento da criação da tabela — definido na instrução CREATE TABLE. Quando um job map-only grava na tabela de saída, ele usa esse schema existente diretamente. Não há mecanismo para especificar ou substituir o schema durante a execução do job.
Como executar um job MapReduce usando o servidor local do MaxCompute?
Use o comando jar no cliente MaxCompute. Para a sintaxe do comando, consulte Enviar um job MapReduce.
Para executar um job programaticamente no servidor, configure JobConf da seguinte forma:
// Configure the MaxCompute connection
Account account = new AliyunAccount(accessid, accesskey);
Odps odps = new Odps(account);
odps.setEndpoint(endpoint);
odps.setDefaultProject(project);
// Initialize the session
SessionState ss = SessionState.get();
ss.setOdps(odps);
ss.setLocalRun(false); // Set to true for local debugging
// Configure the job
Job job = new Job();
job.setResources("mr.jar"); // Equivalent to jar -resources mr.jar
job.setMapperClass(XXXMapper.class);
job.setReducerClass(XXXReducer.class);
Antes de executar o job:
Adicione os JARs de dependência da pasta
libdo seu cliente MaxCompute ao seu classpath. Importe todos os JARs da versão mais recente do cliente.Empacote seu programa MapReduce e faça o upload como um recurso. Para instruções de upload, consulte Operações de recursos.
Erros comuns
Erros de memória e OOM
BufferOverflowException
Um único valor de campo excede o limite de tamanho permitido. Verifique se seus dados obedecem a estes limites por campo:
|
Tipo de dado |
Limite |
|
String |
8 MB |
|
Bigint |
-9.223.372.036.854.775.807 a 9.223.372.036.854.775.807 |
|
Double |
-1,0 x 10^308 a 1,0 x 10^308 |
|
Boolean |
|
|
Date |
0001-01-01 00:00:00 a 9999-12-31 23:59:59 |
O erro completo se parece com:
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)
Erro OOM antes da fase Reduce
Uma quantidade excessiva de dados está sendo mantida na memória durante a fase Map. Evite usar um combiner ou defina odps.mapred.map.min.split.size como 512 para o combiner que você está utilizando.
Erro OOM durante a execução de um job
Aumente a memória heap da Java Virtual Machine (JVM) para mappers ou reducers. Por exemplo, para definir a memória do mapper como 2 GB:
odps.stage.mapper.jvm.mem=2048
java.lang.OutOfMemoryError: Java heap space com muitos reducers
Se você estiver carregando um arquivo de configuração em 600 ou mais reducers e encontrando erros de espaço de heap Java, atingiu um limite de memória do MaxCompute MapReduce. Ajuste os parâmetros relacionados à memória — consulte Visão geral para opções disponíveis. Para os limites aplicáveis, consulte Limites.
Erros de recursos e carregamento de classes
"Resource not found"
O parâmetro -resources não foi definido ao enviar o job. Adicione os recursos necessários:
jar -resources resource1,resource2 ...
Separe múltiplos recursos com vírgulas.
"Class Not Found"
Verifique dois pontos:
Valor de
-classpath: verifique se contém o caminho completo do pacote para o seu JAR, não apenas um diretório.Conteúdo do JAR: certifique-se de que o JAR inclui arquivos
.classcompilados, não apenas arquivos de origem da pastasrc.
Muitos arquivos abertos — limite de referência de recursos excedido
Um único job MapReduce pode referenciar no máximo 256 recursos. Cada tabela e cada arquivo compactado conta como um recurso. O erro completo se parece com:
Caused by: com.aliyun.odps.OdpsException: java.io.FileNotFoundException:
temp/mr_XXXXXX/resource/meta.user.group.config (Too many open files)
Reduza o número de recursos referenciados pelo job. Para a lista completa de limites, consulte Limites.
"Exceed maximum read times per resource" — ODPS-0730001
Os recursos estão sendo lidos vezes demais. Leia cada recurso uma única vez no método setup() e armazene o resultado em cache — não releia dentro dos métodos map() ou reduce().
ODPS-0730001: Exceed maximum read times per resource
Classes de terceiros não encontradas ao usar Maven Assembly
O runtime distribuído do MapReduce está sujeito a restrições do sandbox Java, mas o programa principal não. Se você estiver processando dados JSON, use Gson — ele não precisa ser empacotado no JAR. Para conversão de strings de data, use SimpleDateFormat da biblioteca padrão Java.
Erros de permissões e sandbox
java.security.AccessControlException
Seu código está tentando realizar uma operação que o sandbox Java não permite. O MaxCompute não permite acesso a recursos externos de dentro do sandbox. O erro completo se parece com:
FAILED: ODPS-0123131:User defined function exception - Traceback:
java.lang.ExceptionInInitializerError
...
Caused by: java.security.AccessControlException: access denied
("java.lang.RuntimePermission" "getProtectionDomain")
Para contornar isso, armazene os dados externos ou a lógica de configuração dentro do MaxCompute e leia-os como um recurso. Consulte Exemplo de uso de recursos e Sandbox Java.
ODPS-0420095: access denied — task not in release range
Jobs MapReduce não são suportados na edição developer do MaxCompute. Apenas jobs PyODPS e jobs MaxCompute SQL com funções definidas pelo usuário (UDFs) são suportados nessa edição. Outros jobs, como jobs MapReduce e Spark, não são suportados. O erro completo:
Exception in thread "main" java.io.IOException:
com.aliyun.odps.OdpsException: ODPS-0420095: Access Denied -
The task is not in release range: LOT
Para executar jobs MapReduce, atualize a edição do seu projeto. Consulte Alternar métodos de faturamento.
Erros de entrada, saída e timeout
ODPS-0010000: system internal error — get input pangu dir meta fail
A partição referenciada pelo job não existe ou não contém dados. Crie a partição e insira dados antes de enviar o job.
"Table not found"
O nome do projeto ou o nome da tabela na configuração do job está incorreto, ou a tabela de saída não existe:
Exception in thread "main" com.aliyun.odps.OdpsException:
Table not found: project_name.table_name.
Use TableInfo.Builder e defina tanto ProjectName quanto TableName para corresponder ao projeto e à tabela reais.
ODPS-0123144: Fuxi job failed — WorkerRestart
O nó secundário do cluster atingiu o timeout após 10 minutos e não pode ser alterado, fazendo com que o nó primário o trate como falho. Isso geralmente é causado por um loop grande na fase Reduce — por exemplo, ao processar dados altamente desbalanceados ou gerar produtos cartesianos. Reescreva a lógica do Reduce para evitar loops extensos.
java.io.IOException — muitos maps de execução local
O limite padrão para maps de execução local é 100. Se você estiver atingindo esse limite:
ODPS-0740001: Too many local-run maps: 101, must be <= 100
(specified by local-run parameter 'odps.mapred.local.map.max.tasks')
Adicione -Dodps.mapred.local.map.max.tasks=200 para aumentar o limite.
Subscrito fora dos limites ao executar Hadoop MapReduce no MaxCompute
Reescreva o job usando a API do MaxCompute MapReduce. Se a carga de trabalho exigir, considere usar Spark no MaxCompute.