Proceso de lectura y escritura de datos Hadoop-HDFS (proceso detallado y diagrama)

Distancia de topología de red-nodo

    Distancia de nodo : la suma de las distancias entre dos nodos al ancestro común más cercano.
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

    Si el nodo n1 en el bastidor r1 en el centro de datos d1 se define como / d1 / r1 / n1, se obtendrán los siguientes resultados:

  1. distancia (/ d1 / r1 / n1, / d1 / r1 / n1) = 0 (dos aplicaciones en el mismo nodo)
  2. distancia (/ d1 / r1 / n1, / d1 / r1 / n2) = 2 (dos nodos en el mismo bastidor)
  3. distancia (/ d1 / r1 / n1, / d1 / r2 / n3) = 4 (dos nodos en diferentes racks en el mismo centro de datos)
  4. distancia (/ d1 / r1 / n1, / d2 / r3 / n4) = 6 (dos nodos en diferentes centros de datos)

Proceso de lectura

    Como se muestra en la figura siguiente, suponga que el cliente HDFS necesita leer el archivo one.txt y el archivo one.txt se divide en dos bloques de datos, BlockA y BlockB . El número de copias es 3. BlockA se almacena en D2, D5, D7; BlockB se almacena en D3, D9, D11.
Inserte la descripción de la imagen aquí

El cliente HDFS se comunica con NameNode

  • Debido a que NameNode almacena los metadatos del bloque de datos de one.txt, el cliente necesita enviar una solicitud al NameNode para obtener una lista de DataNodes que almacenan el bloque de datos de one.txt.
  • NameNode recibe la solicitud del cliente y primero verifica los permisos del usuario del cliente. Si el usuario del cliente tiene permisos suficientes, NameNode comprueba si el archivo solicitado existe. Si existe, NameNode enviará una lista de DataNodes que almacenan bloques de datos de one.txt (los DataNodes en la lista están ordenados en orden descendente de la distancia desde el cliente al DataNode). Al mismo tiempo, el NameNode le dará al cliente un token de seguridad.Cuando el cliente accede al DataNode, necesita usar el token para la autenticación.

El cliente HDFS se comunica con DataNode

  • Cuando el cliente recibe la lista de DataNode enviada por el NameNode, el cliente se comunica directamente con el DataNode. Envíe una solicitud al DataNode (BlockA en D2 y BlockB en D3) más cercano al cliente a través del objeto FSDataInputStream . Entre ellos, DFSInputStream gestiona la comunicación entre el cliente y el DataNode.
  • El usuario del cliente muestra el token de seguridad proporcionado por el NameNode al DataNode, y luego comienza a leer datos del DataNode, y los datos fluirán desde el DataNode al cliente en una secuencia.
  • Después de leer todos los bloques de datos, el cliente llama al método close () para cerrar FSDataInputStream.

El proceso detallado de lectura de datos HDFS

  1. El cliente llama al método open () de FileSystem (DistributedFileSystem implementa FileSystem en el sistema de archivos HDFS).
  2. DistributedFileSystem llama de forma remota al NameNode a través de RPC para solicitar la ubicación del DataNode que almacena los primeros bloques de datos de one.txt. Luego, NameNode devuelve las direcciones de todos los DataNodes que almacenan el bloque de datos (NameNode ordena los DataNodes de acuerdo con la distancia del cliente)
  3. Después de open (), DistributedFileSystem devuelve un flujo de entrada FSDataInputStream al cliente. Para HDFS, el flujo de entrada específico es DFSInputStream , y DistributedFileSystem usará DFSInputStream para instanciar FSDataInputStream.
  4. El cliente llama al método read () para leer los datos. El flujo de entrada DFSInputStream selecciona el DataNode más cercano al cliente para establecer una conexión y leer los datos de acuerdo con los resultados de clasificación obtenidos. Luego, los datos fluyen del DataNode al cliente en forma de flujo.
  5. Cuando se lee el bloque de datos, DFSInputStream cierra la conexión con el DataNode. Luego envíe una solicitud al NameNode para obtener la ubicación del siguiente bloque de datos (si la caché del cliente ya contiene la información del bloque de datos, no es necesario solicitar el NameNode)
  6. Encuentre el mejor DataNode para el siguiente bloque de datos y lea los datos.
  7. Si ocurre un error entre el DFSInputStream y el DataNode que se comunica durante el proceso de lectura, el cliente seleccionará otro DataNode más cercano a él. DFSInputStream también marcará aquellos DataNodes que no hayan podido evitar leer estos DataNodes en el siguiente bloque. Al mismo tiempo, DFSInputStream verificará la suma de comprobación de los datos. Si se encuentra un error, informará al NameNode y luego leerá otros DataNodes.
  8. Cuando el cliente lee todos los datos, llama a close () de FSDataInputStream para cerrar el flujo de entrada.

Código

public static void read() throws IOException, InterruptedException, URISyntaxException {
    
    
	Configuration conf = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), conf , "root");
	FSDataInputStream fis = fs.open(new Path("/picture.jpg"));
	FileOutputStream fos = new FileOutputStream("picture.jpg");
	int numBytes = 0;
	byte[] buffer = new byte[1024];
	while ((numBytes = fis.read(buffer)) > 0) {
    
    
		fos.write(buffer, 0, numBytes);
	}
	fis.close();
	fos.close();
	fs.close();
}

Escribir datos

    En una operación de escritura, DFSOutputStream mantiene dos colas, a saber, una cola de datos (cola de datos) y la cola de reconocimiento (cola de ack).
    Suponga que desea escribir el archivo two.txt en HDFS (imagine que NameNode ya ha escrito la información de two.txt y DataNode ya ha escrito datos. El diagrama estático es un poco difícil de dibujar estos dos procesos, solo comprenda el significado)
Inserte la descripción de la imagen aquí

El cliente HDFS se comunica con NameNode

  • Para escribir el archivo two.txt en HDFS, el cliente debe iniciar una solicitud al NameNode. El NameNode primero verifica los permisos del usuario del cliente. Si el usuario tiene permisos suficientes y no hay ningún archivo con el mismo nombre, el NameNode crea un registro correspondiente (metadatos) para el archivo. Si el archivo ya existe, la creación del archivo falla y se informa una IOException.
  • El NameNode proporciona al cliente las direcciones de todos los DataNodes que pueden escribir el archivo two.txt, y el NameNode le dará al cliente un token de seguridad. Antes de que el cliente escriba el DataNode, el token se usa para la autenticación.

El cliente HDFS se comunica con DataNode

  • Una vez que el cliente recibe la lista de DataNode y el permiso de escritura permitido del NameNode, el cliente obtiene la lista de DataNode y el permiso de escritura permitido, y escribe datos directamente en el primer DataNode de la lista. Cuando un DataNode está escribiendo, hará una copia en otro DataNode de acuerdo con el factor de número de copia. Si el factor del número de copias es 3, entonces hay al menos 3 copias de bloques de datos en diferentes DataNodes.
  • Cuando se crea la copia, DataNode enviará un mensaje de confirmación al cliente. Se forma una canalización entre cada DataNode.

El proceso detallado de lectura de datos HDFS

  1. El cliente llama al método create () de FileSystem ( DistributedFileSystem implementa FileSystem en el sistema de archivos HDFS).
  2. DistributedFileSystem llama a NameNode de forma remota a través de RPC para crear un nuevo archivo two.txt en el espacio de nombres del sistema de archivos.
  3. NameNode verifica los permisos del usuario del cliente y también verifica si existe el archivo two.txt. Si el usuario tiene permisos suficientes y no hay ningún archivo con el mismo nombre, NameNode crea el archivo y agrega la información del archivo.
  4. Una vez finalizada la llamada al método remoto, DistributedFileSystem devolverá un flujo de salida FSDataOutputStream al cliente, y este objeto encapsula un DFSOutputStream. El cliente usa write () para escribir datos en HDFS.
  5. Cuando el cliente comienza a escribir datos, DFSOutputStream divide los datos del cliente en varios paquetes de datos y escribe estos paquetes en una cola de datos interna. Entre ellos, DataStreamer usa esta cola de datos para aplicar al NameNode para varios DataNodes que guardan archivos y bloques de datos duplicados. Estos DataNodes formarán una canalización de flujo de datos, y la cantidad de DataNodes en la canalización está determinada por la cantidad de réplicas. DataStreamer envía el paquete de datos al primer DataNode en la canalización, y el primer DataNode guarda el paquete de datos y lo envía al segundo DataNode. De manera similar, el segundo DataNode lo guarda y lo envía al siguiente DataNode, y así sucesivamente.
  6. DFSOutputStream también mantiene una cola de confirmación para recibir información de confirmación del DataNode. Una vez que DataNode crea una copia, enviará la confirmación para asegurar la integridad de los datos. La información de confirmación fluye hacia arriba a lo largo de la canalización del flujo de datos, pasa a través de cada DataNode a su vez y finalmente se envía al cliente. Cuando el cliente recibe la confirmación, borra el paquete correspondiente de la cola de confirmación hasta que se reciben todas las confirmaciones.
  7. El cliente llama al método close () para cerrar el flujo de salida, eliminará todos los datos restantes en la canalización de DataNode y esperará la confirmación. Cuando la cola de confirmación de DFSOutputStream recibe todas las confirmaciones, llamará a complete () para decirle al NameNode que escriba el archivo.

¿Qué sucede si el DataNode falla al escribir datos?

    Al escribir datos, si el DataNode falla, ocurrirán las siguientes operaciones, y estas operaciones son transparentes para el cliente.

  1. La canalización se cerrará y los paquetes de datos en la cola de confirmación se agregarán al frente de la cola de datos para garantizar que los paquetes de datos que se han enviado al DataNode no se pierdan.
  2. El bloque de datos actual en el DataNode normal obtiene un nuevo identificador, y luego este identificador se envía al NameNode para que el DataNode fallido pueda recuperarse y el bloque de datos en este DataNode se pueda eliminar.
  3. Elimine el DataNode fallido de la canalización y construya una nueva canalización para los DataNodes normales restantes, y los datos restantes se escribirán en el DataNode normal a través de la nueva canalización.
  4. Cuando NameNode detecta que el bloque de datos no está lo suficientemente replicado, se encargará de crear una copia adicional en otro DataNode. Los otros bloques de datos próximos se escriben normalmente.

Código

public static void write() throws IOException, InterruptedException, URISyntaxException {
    
    
	Configuration conf = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://master:9000"), conf , "root");
	FileInputStream fis = new FileInputStream("picture.jpg");
	FSDataOutputStream fos = fs.create(new Path("/picture.jpg"));
	int numBytes = 0;
	byte[] buffer = new byte[1024];
	while ((numBytes = fis.read(buffer)) > 0) {
    
    
		fos.write(buffer, 0, numBytes);
	}
	fis.close();
	fos.close();
	fs.close();
}

    Si hay un error, indique (ง • ̀_ • ́) ง (* • ̀ ㅂ • ́) و

    

Supongo que te gusta

Origin blog.csdn.net/H_X_P_/article/details/105777251
Recomendado
Clasificación