Cómo escribir programas MapReduce en Hadoop
1. Descripción general
En 1970, el investigador de IBM Dr. E.F. Codd publicó un artículo titulado "Un modelo relacional de datos para grandes datos compartidos" en la publicación "Comunicación de datos ACM". El artículo de Banks propuso el concepto de modelo relacional, marcando el nacimiento de la base de datos relacional. En las décadas siguientes, la base de datos relacional y su lenguaje de consulta estructurado SQL se convirtieron en una de las habilidades básicas que los programadores deben dominar.
En abril de 2005, Jeffrey Dean y Sanjay Ghemawat publicaron "MapReduce: procesamiento de datos simplificado en grandes clústeres" en la conferencia internacional OSDI, que marcó el lanzamiento público del sistema de procesamiento de datos a gran escala MapReduce de Google. Inspirándose en este artículo, Hadoop fue presentado oficialmente por la Apache Software Foundation en el otoño de ese año como parte del subproyecto Nutch de Lucene. En marzo de 2006, MapReduce y Nutch Distributed File System (NDFS) se incluyeron respectivamente en el proyecto llamado. Hadoop.medio. Hoy en día, Hadoop ha sido utilizado por más del 50% de las empresas de Internet, y muchas otras empresas se están preparando para utilizar Hadoop para procesar cantidades masivas de datos. A medida que Hadoop se vuelva cada vez más popular, tal vez en algún momento en el futuro, Hadoop se convierta en. imprescindible para los programadores. Una de las habilidades, si ese es el caso, aprender a escribir programas MapReduce en Hadoop es el comienzo del aprendizaje de Hadoop.
Este artículo presenta los métodos básicos para escribir programas MapReduce en Hadoop, incluida la composición de los programas MapReduce, los métodos para desarrollar MapReduce en diferentes idiomas, etc.
2. Composición del trabajo de Hadoop
2.1 Proceso de ejecución del trabajo de Hadoop
El usuario configura y menciona un trabajo de Hadoop en el marco de Hadoop, y el marco de Hadoop se descompondrá. en una serie de tareas de mapa y reducir tareas. El marco Hadoop es responsable de la distribución y ejecución de tareas, la recopilación de resultados y el seguimiento del progreso del trabajo.
La siguiente figura muestra las etapas por las que pasa un trabajo de principio a fin y quién controla cada etapa (usuario o marco Hadoop).
La siguiente figura detalla el trabajo que los usuarios deben realizar al escribir trabajos de MapReduce y el trabajo que el marco Hadoop completa automáticamente:
Al escribir programas MapReduce, los usuarios especifican a través de InputFormat y OutputFormat respectivamente, formatos de entrada y salida, y define Mapper y Reducer para especificar el trabajo a realizar en la fase de mapa y en la fase de reducción. En Mapper o Reducer, los usuarios solo necesitan especificar la lógica de procesamiento de un par de claves/valores, y el marco Hadoop analizará automáticamente todas las claves/valores de forma secuencial e iterativa, y entregará cada par de claves/valores a Mapper. o Reductor para su procesamiento. En la superficie, Hadoop limita el formato de datos a clave/valor, lo cual es demasiado simple y difícil de resolver problemas complejos. De hecho, la clave o el valor se pueden crear mediante una combinación de métodos (como guardar varios campos en clave o valor, cada Los campos están separados por delimitadores, o el valor es un objeto serializado cuando se usa en Mapper, deserialícelo, etc.) para guardar información múltiple para resolver aplicaciones con formatos de entrada más complejos.
2.2 Trabajo del usuario
Las clases o métodos que los usuarios deben implementar al escribir MapReduce son:
(1) Interfaz InputFormat
Necesidades del usuario Implemente esta interfaz para especificar el formato de contenido del archivo de entrada.
Esta interfaz tiene dos métodos
1
2
3
4
5
6
7
8
9
10
11
interfaz pública InputFormat
InputSplit[] getSplits(JobConf job, int numSplits) lanza IOException;
RecordReader Trabajo JobConf, Reporter reporter) arroja IOException; } La función getSplits divide todos los datos de entrada en numSplits, cada uno Cada división se entrega a una tarea de mapa para su procesamiento. La función getRecordReader proporciona un objeto iterador para que el usuario analice la división, que analiza cada registro de la división en un par clave/valor. Hadoop proporciona algunos formatos de entrada: (2) Interfaz Mapper Los usuarios deben heredar la interfaz Mapper para implementar su propio Mapper. implementados en el Mapper son 1 2 3 4 5 6 7 8 9 mapa vacío (tecla K1, V1 value, OutputCollector Reporter reporter ) arroja IOException Entre ellos, Hadoop proporciona algunos Mapper para que los usuarios los utilicen: (3) Interfaz del Particionador Los usuarios deben heredar esta interfaz para implementar su propio Particionador para especificar el mapa. generación de tareas Se asigna el par clave/valor a la que se reduce la tarea para su procesamiento. Un buen particionador puede hacer que los datos procesados por cada tarea de reducción sean similares, logrando así el equilibrio de carga. La función que debe implementarse en Partitioner es getPartition(K2 key, V2 value, int numPartitions) Esta función devuelve el ID de la tarea de reducción correspondiente a Si el usuario no proporciona un particionador, Hadoop utilizará el predeterminado (en realidad, una función hash). (4) Combiner Combiner reduce en gran medida la cantidad de transmisión de datos entre tareas de mapas y reduce las tareas, lo que puede mejorar significativamente el rendimiento. En la mayoría de los casos, Combiner es lo mismo que Reducer. (5) Interfaz Reducer Los usuarios deben heredar la interfaz Reducer para implementar su propio Reducer. Las funciones que deben implementarse en Reducer son 1. 2 3 4 5 6 7 p> 8 9 reducción de vacío (tecla K2, valores de Iterador OutputCollector Reporter reporter ) arroja IOException El propio Hadoop proporciona algunos reductores para que los usen los usuarios: (6 ) OutputFormat Los usuarios especifican el formato de contenido del archivo de salida a través de OutputFormat, pero no se divide. Cada tarea de reducción escribe sus datos en su propio archivo, llamado part-nnnnn, donde nnnnn es el ID de la tarea de reducción. Hadoop proporciona varios formatos de salida: 3. Caché distribuido Haoop viene con un caché distribuido, el objeto DistributedCache, que facilita el mapa. Parte de la información se comparte entre ellos. Tareas o reducir tareas. Por ejemplo, en algunas aplicaciones prácticas, todas las tareas del mapa deben leer el mismo archivo de configuración o diccionario, y el archivo de configuración o diccionario se puede colocar en el caché distribuido. 4. Escribir trabajos de MapReduce en varios idiomas Hadoop está escrito en Java, por lo que Hadoop naturalmente admite trabajos de escritura en lenguaje Java. Sin embargo, en aplicaciones reales, a veces es necesario hacerlo. Si se utilizan bibliotecas de terceros u otras razones, es necesario utilizar C/C++ u otros lenguajes para escribir trabajos de MapReduce. En este momento, es posible que deba utilizar algunas herramientas proporcionadas por Hadoop. Si desea escribir trabajos de MpaReduce en C/C++, las herramientas que puede utilizar incluyen Hadoop Streaming o Hadoop Pipes. Si desea escribir trabajos de MapReduce en Python, puede usar Hadoop Streaming o Pydoop. Si deseas utilizar otros lenguajes, como shell, php, ruby, etc., puedes utilizar Hadoop Streaming. Para la programación de Hadoop Streaming, consulte la publicación de mi blog: "Programación de Hadoop Streaming" (/projects/pydoop/ Para la programación de tuberías de Hadoop, consulte "Tutorial de Hadoop 2.2 — Ejecutando programas C++ en Hadoop". 5. Comparación de métodos de programación (1) Java es el mejor y más completo lenguaje compatible con Hadoop y proporciona muchas herramientas para facilitar el desarrollo del programador. (2) Hadoop Streaming Su mayor ventaja es que admite múltiples idiomas, pero su eficiencia es baja. La tarea de reducción no se puede iniciar hasta que se completa la fase del mapa. InputFormat. Si desea especificar el formato del archivo de entrada, puede escribirlo en lenguaje Java o especificar el delimitador en la línea de comando. Utiliza entrada y salida estándar para permitir que C/C++ se comunique con Java, por lo que solo admite datos de texto; formato (3). Hadoop Pipes Está especialmente diseñado para el lenguaje C/C++ Debido a que utiliza sockets para comunicarse entre C/C++ y Java, su eficiencia es baja (su ventaja es que requiere). una gran cantidad de trabajos y es muy rápido C/C++) para escribir RecordReader. (4)Pydoop. Está especialmente diseñado para facilitar a los programadores de Python escribir trabajos de MapReduce. Su capa inferior utiliza la interfaz Hadoop Streaming y la biblioteca libhdfs. 6. Resumen Hadoop hace que escribir programas distribuidos sea extremadamente simple. En muchos casos, los usuarios solo necesitan escribir dos funciones: map() y reduce() (InputFormat, Outputformat puede ser. utilizado como valor predeterminado del sistema). Es precisamente por la simplicidad de la programación de Hadoop que cada vez más empresas o unidades de investigación comienzan a utilizar Hadoop.