Para comprender el lector de registros en Hadoop, necesitamos comprender el flujo de datos en hadoop. Veamos cómo fluyen los datos:
MapReduce tiene un modelo simple de procesamiento de datos: las entradas y salidas para el mapa y las funciones de reducción son pares clave-valor. Las funciones map y reduce en Hadoop MapReduce tienen la siguiente forma general:
mapa: (K1, V1) → lista (K2, V2)
reducir: (K2, lista (V2)) → lista (K3, V3)
Ahora, antes de procesar, necesita saber qué datos procesar, esto se logra con la clase InputFormat . InputFormat es la clase que selecciona el archivo de HDFS que se debe ingresar a la función de mapa. Un InputFormat también es responsable de crear las divisiones de entrada y dividirlas en registros. Los datos se dividen en número de divisiones (generalmente 64 / 128mb) en HDFS. Una división de entrada es una porción de la entrada que es procesada por un solo mapa.
La clase InputFormat llama a la función getSplits () y calcula las divisiones para cada archivo y luego los envía al rastreador de trabajos, que utiliza sus ubicaciones de almacenamiento para programar tareas de mapa para procesarlas en los rastreadores de tareas. En un rastreador de tareas, la tarea de mapa pasa la división al método createRecordReader () en InputFormat para obtener un RecordReader para esa división. RecordReader carga datos de su fuente y los convierte en pares clave-valor adecuados para leer con el mapeador. El InputFormat predeterminado es TextInputFormat, que trata cada valor de entrada como un nuevo valor y la clave asociada es el desplazamiento de bytes.
Un RecordReader es poco más que un iterador sobre registros, y la tarea de mapeo usa uno para generar pares de clave-valor de registro, que pasa a la función de mapa. Podemos ver esto mirando el método run () de Mapper:
public void run (Context context) arroja IOException, InterruptedException {
configuración (contexto);
while (context.nextKeyValue ()) {
map (context.getCurrentKey (), context.getCurrentValue (), context);
}
limpieza (contexto);
}
Después de ejecutar setup (), se invoca repetidamente nextKeyValue () en el Contexto (que delega al método con el mismo nombre en RecordReader) para completar los objetos clave y de valor para el asignador. La clave y el valor se recuperan del Lector de registros a través del contexto, y se pasan al método map () para que haga su trabajo. La entrada a la función de mapa que es el par clave-valor (K, V) se procesa según la lógica mencionada en el código del mapa.
Cuando el lector llega al final de la secuencia, el método nextKeyValue () devuelve falso y la tarea de mapa ejecuta su método cleanup () .
La salida del mapeador se envía al particionador. Partitioner controla la partición de las claves de las salidas de mapa intermedias. La clave (o un subconjunto de la clave) se utiliza para derivar la partición, generalmente mediante una función hash. El número total de particiones es igual al número de tareas de reducción para el trabajo. Por lo tanto, esto controla cuál de las m tareas de reducción envía la clave intermedia (y, por lo tanto, el registro) para su reducción. El uso de particionadores es opcional.
Todos los valores correspondientes a la misma clave irán al mismo reductor.
La salida del mapeador se escribe primero en el disco local para el proceso de clasificación y barajado . También está en forma de par clave-valor. Y luego se fusiona y finalmente se entrega al reductor.
MapReduce garantiza que la entrada a cada reductor está ordenada por clave. El proceso por el cual el sistema realiza la clasificación, y transfiere las salidas del mapa a los reductores como entradas, se conoce como la combinación aleatoria . Se dice que el shuffle es el corazón de MapReduce y es donde ocurre la “magia”.
La salida de todos los mapeadores va a todos los reductores. Durante la fase de reducción, la función de reducción se invoca para cada tecla en la salida ordenada. El resultado de esta fase se escribe en el sistema de archivos de salida, generalmente HDFS. El par clave-valor proporcionado como salida por el reductor se pasa a OutputFormat, que luego se escribe en HDFS. También proporciona la clase RecordWriter que escribe registros individuales en el archivo mencionado en setOutputPath (). Cada reductor escribe un archivo separado en el directorio de salida y estos archivos se nombran como parte-00000.
También se puede usar el combinador para el propósito de optimización. Combiner se coloca conceptualmente después del bloque de mapa y reduce la salida particular de ese bloque de mapa. Generalmente se denomina mini-reductor. También reduce el retraso de la red.