Tecnología de big data: construcción de entrada Hadoop3.X + instalación y ajuste (2.HDFS)

1. Descripción general de HDFS

1.1 Fondo y definición de salida HDFS

1) Antecedentes de HDFS
Con la creciente cantidad de datos, todos los datos no se pueden almacenar en un sistema operativo, por lo que se asignan a más discos administrados por el sistema operativo, pero es un inconveniente administrarlo y mantenerlo, y existe una necesidad urgente de un sistema Para administrar archivos en varias máquinas, este es un sistema de administración de archivos distribuido. HDFS es solo un tipo de sistema de administración de archivos distribuidos.
2) HDFS define
HDFS (Sistema de archivos distribuidos de Hadoop), que es un sistema de archivos para almacenar y ubicar archivos a través de árboles de directorios; en segundo lugar, está distribuido y muchos servidores se combinan para realizar sus funciones. Los servidores tienen sus propias funciones.
El escenario de uso de HDFS: es adecuado para el escenario de escribir una vez y leer muchas veces. No es necesario cambiar un archivo después de crearlo, escribirlo y cerrarlo.

1.2 Ventajas y desventajas de HDFS

Ventajas de HDFS
1) Alta tolerancia a fallas
➢ Se guardan automáticamente múltiples copias de datos. Mejora la tolerancia a fallas al agregar copias.
inserte la descripción de la imagen aquí

➢ Después de perder una copia, se puede restaurar automáticamente.
inserte la descripción de la imagen aquí

2) Adecuado para el procesamiento de big data
➢ Escala de datos: puede manejar datos con una escala de datos que alcanza el nivel de GB, TB o incluso PB;
➢ Escala de archivos: puede manejar la cantidad de archivos por encima de un millón, que es bastante grande.
3) Puede construirse en máquinas baratas y la confiabilidad puede mejorarse a través del mecanismo de copias múltiples.
Desventajas de HDFS
1) No es adecuado para el acceso a datos de baja latencia, como el almacenamiento de datos en milisegundos, lo cual es imposible.
2) No puede almacenar de manera eficiente una gran cantidad de archivos pequeños.
➢ Si almacena una gran cantidad de archivos pequeños, ocupará una gran cantidad de memoria de NameNode para almacenar el directorio de archivos y
bloquear la información. Esto no es recomendable, porque la memoria de NameNode siempre es limitada;
➢ El tiempo de direccionamiento del almacenamiento de archivos pequeños excederá el tiempo de lectura, lo que viola el objetivo de diseño de HDFS.
3) No se admiten la escritura simultánea ni la modificación aleatoria de archivos.
➢ Un archivo solo puede ser escrito por uno, y múltiples subprocesos no pueden escribir al mismo tiempo;
➢ Solo se admite la adición de datos (adjuntar), y no se admite la modificación aleatoria de archivos.
inserte la descripción de la imagen aquí

1.3 Estructura HDFS

1) NameNode (nn): Es el Maestro, que es supervisor y administrador.
(1) Administrar el espacio de nombres HDFS;
(2) Configurar la estrategia de copia;
(3) Administrar la información de mapeo del bloque de datos (Bloque);
(4) Procesar las solicitudes de lectura y escritura del cliente.
2) DataNode: Es Esclavo. NameNode emite comandos y DataNode realiza las operaciones reales.
(1) almacenar el bloque de datos real;
(2) realizar la operación de lectura/escritura del bloque de datos.
inserte la descripción de la imagen aquí
3) Cliente: Es el cliente.
(1) Segmentación de archivos. Cuando se carga un archivo en HDFS, el Cliente divide el archivo en bloques y luego lo carga;
(2) Interactúa con NameNode para obtener la información de ubicación del archivo;
(3) Interactúa con DataNode para leer o escribir datos;
( 4) El cliente proporciona algunos comandos para administrar HDFS, como el formateo de NameNode;
(5) El cliente puede acceder a HDFS a través de algunos comandos, como agregar, eliminar, verificar y modificar HDFS;
4) NameNode secundario: no es la copia de seguridad activa de NameNode. Cuando el NameNode cuelga, no puede reemplazar inmediatamente al NameNode y proporcionar servicios.
(1) ayudar a NameNode a compartir su carga de trabajo, como fusionar regularmente Fsimage y Edits y enviarlos a NameNode;
(2) en caso de emergencia, puede ayudar a recuperar NameNode.

1.4 Tamaño de bloque de archivo HDFS (enfoque de entrevista)

Los archivos en HDFS se almacenan físicamente en bloques (Block). El tamaño del bloque se puede especificar mediante el parámetro de configuración (dfs.blocksize). El tamaño predeterminado es 128M en la versión Hadoop2.x/3.x y la versión 1.x. Son 64M.
inserte la descripción de la imagen aquí
Pensando: ¿Por qué el tamaño del bloque no puede establecerse demasiado pequeño o demasiado grande?
(1) La configuración del bloque HDFS es demasiado pequeña, lo que aumentará el tiempo de búsqueda, y el programa siempre está buscando la posición de inicio del bloque; (2)
Si la configuración del bloque es demasiado grande, el tiempo para transferir datos desde el disco será significativamente más largo que el tiempo requerido para ubicar la posición de inicio del bloque de tiempo requerido. Como resultado, el programa será muy lento al procesar este dato.
Resumen: la configuración del tamaño del bloque HDFS depende principalmente de la velocidad de transferencia del disco.

2. Operación Shell de HDFS (enfoque de desarrollo)

2.1 Sintaxis básica

hadoop fs 具体命令 OR hdfs dfs 具体命令
两个是完全相同的。

2.2 Enciclopedia de comandos

[xusheng@hadoop102 hadoop-3.1.3]$ bin/hadoop fs

[-appendToFile <localsrc> ... <dst>]
		[-cat [-ignoreCrc] <src> ...]
		[-chgrp [-R] GROUP PATH...]
		[-chmod [-R] <MODE[,MODE]... | OCTALMODE> PATH...]
		[-chown [-R] [OWNER][:[GROUP]] PATH...]
		[-copyFromLocal [-f] [-p] <localsrc> ... <dst>]
		[-copyToLocal [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
		[-count [-q] <path> ...]
		[-cp [-f] [-p] <src> ... <dst>]
		[-df [-h] [<path> ...]]
		[-du [-s] [-h] <path> ...]
		[-get [-p] [-ignoreCrc] [-crc] <src> ... <localdst>]
		[-getmerge [-nl] <src> <localdst>]
		[-help [cmd ...]]
		[-ls [-d] [-h] [-R] [<path> ...]]
		[-mkdir [-p] <path> ...]
		[-moveFromLocal <localsrc> ... <dst>]
		[-moveToLocal <src> <localdst>]
		[-mv <src> ... <dst>]
		[-put [-f] [-p] <localsrc> ... <dst>]
		[-rm [-f] [-r|-R] [-skipTrash] <src> ...]
		[-rmdir [--ignore-fail-on-non-empty] <dir> ...]
<acl_spec> <path>]]
		[-setrep [-R] [-w] <rep> <path> ...]
		[-stat [format] <path> ...]
		[-tail [-f] <file>]
		[-test -[defsz] <path>]
		[-text [-ignoreCrc] <src> ...]

2.3 Funcionamiento práctico de los comandos comunes

2.3.1 Preparaciones

1) Inicie el clúster de Hadoop (para facilitar las pruebas posteriores)

[xusheng@hadoop102 hadoop-3.1.3]$ sbin/start-dfs.sh
[xusheng@hadoop103 hadoop-3.1.3]$ sbin/start-yarn.sh

2) -ayuda: genera este parámetro de comando

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -help rm

3) Crear carpeta /sanguo

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /sanguo

inserte la descripción de la imagen aquí

2.3.2 Subir

1) -moveFromLocal: cortar y pegar de local a HDFS

[xusheng@hadoop102 hadoop-3.1.3]$ vim shuguo.txt
输入:
shuguo
[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -moveFromLocal ./shuguo.txt /sanguo

inserte la descripción de la imagen aquí

2) -copyFromLocal: copia archivos del sistema de archivos local a la ruta HDFS

[xusheng@hadoop102 hadoop-3.1.3]$ vim weiguo.txt
输入:
weiguo
[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -copyFromLocal weiguo.txt /sanguo

inserte la descripción de la imagen aquí

3) -put: equivalente a copyFromLocal, el entorno de producción está más acostumbrado a usar put

[xusheng@hadoop102 hadoop-3.1.3]$ vim wuguo.txt
输入:
wuguo
[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -put ./wuguo.txt /sanguo

4) -appendToFile: agrega un archivo al final de un archivo existente

[xusheng@hadoop102 hadoop-3.1.3]$ vim liubei.txt
输入:
liubei
[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -appendToFile liubei.txt /sanguo/shuguo.txt

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

2.3.3 descargar

1) -copyToLocal: copiar de HDFS a local

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -copyToLocal /sanguo/shuguo.txt ./

2) -get: equivalente a copyToLocal, el entorno de producción está más acostumbrado a usar get

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -get /sanguo/shuguo.txt ./shuguo2.txt

inserte la descripción de la imagen aquí

2.3.4 Operación directa de HDFS

1) -ls: mostrar información del directorio

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -ls /sanguo

2) -cat: mostrar el contenido del archivo

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -cat /sanguo/shuguo.txt

inserte la descripción de la imagen aquí

3) -chgrp, -chmod, -chown: el uso en el sistema de archivos de Linux es el mismo, modifique los permisos del archivo

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -chmod 666 /sanguo/shuguo.txt
[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -chown xusheng:xusheng /sanguo/shuguo.txt

inserte la descripción de la imagen aquí

4) -mkdir: crear ruta

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -mkdir /jinguo

5) -cp: copia de una ruta de HDFS a otra ruta de HDFS

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -cp /sanguo/shuguo.txt /jinguo

6) -mv: Mover archivos en el directorio HDFS

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -mv /sanguo/wuguo.txt /jinguo
[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -mv /sanguo/weiguo.txt /jinguo

7) -tail: muestra los datos finales de 1kb de un archivo

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -tail /jinguo/shuguo.txt

inserte la descripción de la imagen aquí

8) -rm: eliminar archivos o carpetas

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -rm /sanguo/shuguo.txt

9) -rm -r: Elimina recursivamente el directorio y el contenido del directorio

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -rm -r /sanguo

10) información sobre el tamaño de la carpeta de estadísticas -du

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -du -s -h /jinguo
27 81 /jinguo
[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -du -h /jinguo
14 42 /jinguo/shuguo.txt
7 21 /jinguo/weiguo.txt
6 18 /jinguo/wuguo.tx

11) -setrep: establece el número de copias de archivos en HDFS

[xusheng@hadoop102 hadoop-3.1.3]$ hadoop fs -setrep 10 /jinguo/shuguo.txt

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

El número de réplicas establecido aquí solo se registra en los metadatos del NameNode. Si realmente hay tantas réplicas depende de la cantidad de DataNodes. Debido a que actualmente solo hay dispositivos 3, hay copias como máximo 3. Solo cuando la cantidad de nodos aumenta a 10, la cantidad de copias puede llegar a 10.

3. Operación API de HDFS

3.1 Preparación del entorno del cliente

1) Busque la carpeta de dependencia de Windows en la ruta del paquete de datos y copie hadoop-3.1.0 en una ruta que no sea china (como d:\).

链接:https://pan.baidu.com/s/1PqNnlBNCTW1h7HuyxT4hYw 
提取码:9oz7 

2) Configurar la variable de entorno HADOOP_HOME
inserte la descripción de la imagen aquí
3) Configurar la variable de entorno Path.
Nota: si las variables de entorno no funcionan, puede reiniciar la computadora
inserte la descripción de la imagen aquí
para verificar que las variables de entorno de Hadoop sean normales. Haga doble clic en winutils.exe, si se informa el siguiente error. Significa que falta la biblioteca de tiempo de ejecución de Microsoft (los sistemas originales a menudo tienen este problema). En el paquete de datos, hay un paquete de instalación de tiempo de ejecución de Microsoft correspondiente, haga doble clic para instalarlo.
inserte la descripción de la imagen aquí
4) Cree un proyecto Maven HdfsClientDemo en IDEA e importe las coordenadas de dependencia correspondientes + adición de registro

<dependencies>
	<dependency>
		<groupId>org.apache.hadoop</groupId>
		<artifactId>hadoop-client</artifactId>
		<version>3.1.3</version>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>4.12</version>
	</dependency>
	<dependency>
		<groupId>org.slf4j</groupId>
		<artifactId>slf4j-log4j12</artifactId>
		<version>1.7.30</version>
	</dependency>
</dependencies>

En el directorio src/main/resources del proyecto, cree un nuevo archivo llamado "log4j.properties", complete el archivo

log4j.rootLogger=INFO, stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/spring.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n

5) Crear el nombre del paquete: com.xusheng.hdfs
6) Crear la clase HdfsClient

3.2 Caso práctico de la API de HDFS

3.2.1 Carga de archivos HDFS (prioridad de parámetros de prueba)

1) Escribir código fuente

@Test
public void testCopyFromLocalFile() throws IOException,InterruptedException, URISyntaxException {
    
    
	// 1 获取文件系统
	Configuration configuration = new Configuration();
	configuration.set("dfs.replication", "2");
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"),
	configuration, "xusheng");
	// 2 上传文件
	fs.copyFromLocalFile(new Path("d:/sunwukong.txt"), new
	Path("/xiyou/huaguoshan"));
	// 3 关闭资源
	fs.close();

2) Copie hdfs-site.xml al directorio de recursos del proyecto

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
	<property>
		<name>dfs.replication</name>
		<value>1</value>
	</property>
</configuration>

3) Prioridad de parámetros
Clasificación de prioridad de parámetros: (1) el valor establecido en el código del cliente > (2) el archivo de configuración definido por el usuario en ClassPath > (3) luego la configuración personalizada del servidor (xxx-site.xml) >(4) La configuración predeterminada del servidor (xxx-default.xml)
inserte la descripción de la imagen aquí

3.2.2 Descarga de archivos HDFS

@Test
public void testCopyToLocalFile() throws IOException,InterruptedException, URISyntaxException{
    
    
	// 1 获取文件系统
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"),
	configuration, "xusheng");
	// 2 执行下载操作
	// boolean delSrc 指是否将原文件删除
	// Path src 指要下载的文件路径
	// Path dst 指将文件下载到的路径
	// boolean useRawLocalFileSystem 是否开启文件校验
	fs.copyToLocalFile(false, new
	Path("/xiyou/huaguoshan/sunwukong.txt"), new Path("d:/sunwukong2.txt"),true);
	// 3 关闭资源
	fs.close();
}

**Nota:** Si se ejecuta el código anterior y no se puede descargar el archivo, es posible que su computadora no tenga suficientes bibliotecas de tiempo de ejecución compatibles con Microsoft y necesite instalar las bibliotecas de tiempo de ejecución de Microsoft.

3.2.3 Renombrar y mover archivos HDFS

@Test
public void testRename() throws IOException, InterruptedException,URISyntaxException{
    
    
	// 1 获取文件系统
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"),
	configuration, "xusheng");
	// 2 修改文件名称
	fs.rename(new Path("/xiyou/huaguoshan/sunwukong.txt"), newPath("/xiyou/huaguoshan/meihouwang.txt"));
	// 3 关闭资源
	fs.close();
}

3.2.4 HDFS eliminar archivos y directorios

@Test
public void testDelete() throws IOException, InterruptedException,URISyntaxException{
    
    
	// 1 获取文件系统
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"),
	configuration, "xusheng");
	// 2 执行删除
	fs.delete(new Path("/xiyou"), true);
	// 3 关闭资源
	fs.close();
}

3.2.5 Ver detalles del archivo HDFS

Ver nombre de archivo, permisos, longitud, información de bloqueo

@Test
public void testListFiles() throws IOException, InterruptedException,URISyntaxException {
    
    
	// 1 获取文件系统
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"),
	configuration, "xusheng");
	// 2 获取文件详情
	RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"),true);
	while (listFiles.hasNext()) {
    
    
		LocatedFileStatus fileStatus = listFiles.next();
		System.out.println("========" + fileStatus.getPath() + "=========");
		System.out.println(fileStatus.getPermission());
		System.out.println(fileStatus.getOwner());
		System.out.println(fileStatus.getGroup());
		System.out.println(fileStatus.getLen());
		System.out.println(fileStatus.getModificationTime());
		System.out.println(fileStatus.getReplication());
		System.out.println(fileStatus.getBlockSize());
		System.out.println(fileStatus.getPath().getName());
		// 获取块信息
		BlockLocation[] blockLocations = fileStatus.getBlockLocations();
		System.out.println(Arrays.toString(blockLocations));
	}
	// 3 关闭资源
	fs.close();
}

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

3.2.6 Valoración de carpetas y archivos HDFS

@Test
public void testListStatus() throws IOException, InterruptedException,URISyntaxException{
    
    
	// 1 获取文件配置信息
	Configuration configuration = new Configuration();
	FileSystem fs = FileSystem.get(new URI("hdfs://hadoop102:8020"),
	configuration, "xusheng");
	// 2 判断是文件还是文件夹
	FileStatus[] listStatus = fs.listStatus(new Path("/"));
	for (FileStatus fileStatus : listStatus) {
    
    
	// 如果是文件
		if (fileStatus.isFile()) {
    
    
		System.out.println("f:"+fileStatus.getPath().getName());
		}else {
    
    
		System.out.println("d:"+fileStatus.getPath().getName());
		}
	}
	// 3 关闭资源
	fs.close();
}

inserte la descripción de la imagen aquí

3.2.7 Código encapsulado

package com.xusheng.hdfs;

import org.junit.Test;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.*;
import org.apache.hadoop.io.IOUtils;
import org.apache.hadoop.yarn.webapp.hamlet2.Hamlet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.util.Arrays;


/**
 * 客户端代码常用套路
 * 1.获取一个客户端对象
 * 2.执行相关的操作命令
 * 3.关闭资源
 * HDFS zookeeper
 */
public class HdfsClient {
    
    

    private FileSystem fs;
    @Before
    public void init() throws IOException, InterruptedException, URISyntaxException {
    
    
        // 连接的集群nn地址
        URI uri = new URI("hdfs://hadoop102:8020");
        // 创建一个配置文件
        Configuration configuration = new Configuration();

        configuration.set("dfs.replication", "2");
        // 用户
        String user = "xusheng";
        //1.获取一个客户端对象
        fs = FileSystem.get(uri,configuration,user);
    }

    @After
    public void close() throws IOException {
    
    
        //3.关闭资源
        fs.close();
    }

    @Test
    public void testmkdir() throws URISyntaxException, IOException, InterruptedException {
    
    

        //2 创建一个文件夹
        fs.mkdirs(new Path("/xiyou/huaguoshan"));

    }
    // 上传
    /**
     * 参数优先级
     * hdfs-default.xml => hdfs-site.xml=> 在项目资源目录下的配置文件 =》代码里面的配置
     *
     * @throws IOException
     */
    @Test
    public void testPut() throws IOException {
    
    
        // 参数解读:参数一:表示删除原数据;
        // 参数二:是否允许覆盖;
        // 参数三:原数据路径; 参数四:目的地路径
        fs.copyFromLocalFile(false,true,new Path("D:\\sunwukong.txt"),new Path("hdfs://hadoop102/xiyou/huaguoshan"));
    }
    @Test
    public void testPut2() throws IOException {
    
    
        FSDataOutputStream fos = fs.create(new Path("/input"));

        fos.write("hello world".getBytes());
    }

    // 文件下载
    @Test
    public void testGet() throws IOException {
    
    
        // 参数的解读:参数一:原文件是否删除;参数二:原文件路径HDFS; 参数三:目标地址路径Win ; 参数四:
        fs.copyToLocalFile(true, new Path("hdfs://hadoop102/xiyou/huaguoshan/"), new Path("D:\\"), true);
        //fs.copyToLocalFile(false, new Path("hdfs://hadoop102/a.txt"), new Path("D:\\"), false);
    }
    // 删除
    @Test
    public void  testRm() throws IOException {
    
    
        // 参数解读:参数1:要删除的路径; 参数2 : 是否递归删除
        // 删除文件
        //fs.delete(new Path("/jdk-8u212-linux-x64.tar.gz"),false);

        // 删除空目录
        //fs.delete(new Path("/xiyou"), false);

        // 删除非空目录
        fs.delete(new Path("jinguo"),true);
    }
    // 文件的更名和移动
    @Test
    public void testmv() throws IOException {
    
    
        // 参数解读:参数1 :原文件路径; 参数2 :目标文件路径
        // 对文件名称的修改
        //fs.rename(new Path("/input/word.txt"), new Path("/input/ss.txt"));

        // 文件的移动和更名
        //fs.rename(new Path("/input/ss.txt"),new Path("/cls.txt"));

        // 目录更名
        fs.rename(new Path("/input"), new Path("/output"));

    }

    // 获取文件详细信息
    @Test
    public void fileDetail() throws IOException {
    
    

        // 获取所有文件信息
        RemoteIterator<LocatedFileStatus> listFiles = fs.listFiles(new Path("/"), true);

        // 遍历文件
        while (listFiles.hasNext()) {
    
    
            LocatedFileStatus fileStatus = listFiles.next();

            System.out.println("==========" + fileStatus.getPath() + "=========");
            System.out.println(fileStatus.getPermission());
            System.out.println(fileStatus.getOwner());
            System.out.println(fileStatus.getGroup());
            System.out.println(fileStatus.getLen());
            System.out.println(fileStatus.getModificationTime());
            System.out.println(fileStatus.getReplication());
            System.out.println(fileStatus.getBlockSize());
            System.out.println(fileStatus.getPath().getName());

            // 获取块信息
            BlockLocation[] blockLocations = fileStatus.getBlockLocations();

            System.out.println(Arrays.toString(blockLocations));

        }
    }

    // 判断是文件夹还是文件
    @Test
    public void testFile() throws IOException {
    
    

        FileStatus[] listStatus = fs.listStatus(new Path("/"));

        for (FileStatus status : listStatus) {
    
    

            if (status.isFile()) {
    
    
                System.out.println("文件:" + status.getPath().getName());
            } else {
    
    
                System.out.println("目录:" + status.getPath().getName());
            }
        }
    }

}

4. El proceso de lectura y escritura de HDFS (enfoque de entrevista)

4.1 Proceso de escritura de datos HDFS

4.1.1 Escritura del archivo de análisis

Proceso de escritura de datos HDFS
inserte la descripción de la imagen aquí
(1) El cliente solicita a NameNode que cargue archivos a través del módulo Distributed FileSystem, y NameNode verifica si existe el archivo de destino y si existe el directorio principal.
(2) NameNode devuelve si se puede cargar.
(3) A qué servidores de DataNode solicita el cliente cargar el primer Bloque.
(4) NameNode devuelve tres nodos DataNode, a saber, dn1, dn2 y dn3.
(5) El cliente solicita a dn1 que cargue datos a través del módulo FSDataOutputStream. Después de recibir la solicitud, dn1 continuará llamando a dn2, y luego dn2 llamará a dn3 para completar el establecimiento del canal de comunicación.
(6) dn1, dn2 y dn3 responden a los clientes paso a paso.
(7) El cliente comienza a cargar el primer bloque a dn1 (primero lee los datos del disco y los coloca en un caché de memoria local), tomando el Paquete como unidad, dn1 recibe un Paquete y luego lo pasa a dn2, y dn2 lo pasa a dn3; dn1 Cada vez que se transmite un paquete, se colocará en una cola de respuesta para esperar la respuesta.
(8) Una vez completada la transmisión de un Bloque, el cliente solicita al NameNode que cargue el servidor del segundo Bloque nuevamente. (Repita los pasos 3-7).

4.1.2 Topología de red - cálculo de distancia de nodo

Durante el proceso de escritura de datos en HDFS, NameNode seleccionará el DataNode con la distancia más cercana a los datos que se cargarán para recibir los datos. Entonces, ¿cómo calcular la distancia más corta?
Distancia de nodo: la suma de las distancias entre dos nodos a su ancestro común más cercano.

Distancia(/d1/r1/n0,/d1/r1/n0)=0 (procesos en el mismo nodo)
Distancia(/d1/r2/n0,/d1/r3/n2)=4 (diferentes racks en los mismos datos nodos centrales en el mismo bastidor)
Distancia (/d1/r1/n1,/d1/r1/n2)=2 (diferentes nodos en el mismo bastidor)
Distancia (/d1/r2/n1,/d2/r4/n1)= 6 (nodos en diferentes centros de datos)

inserte la descripción de la imagen aquí
Por ejemplo, suponga que hay un nodo n1 en el bastidor r1 en el centro de datos d1. Este nodo se puede representar como /d1/r1/n1. Usando esta notación, aquí se dan cuatro descripciones de distancia.
Calcular la distancia entre cada dos nodos.
inserte la descripción de la imagen aquí

4.1.3 Conciencia de rack (selección de nodo de almacenamiento de replicación)

1) Descripción de Rack Aware
(1)
Enlace de descripción oficial: http://hadoop.apache.org/docs/r3.1.3/hadoop-project-dist/hadoop-hdfs/HdfsDesign.html#Data_Replication .

For the common case, when the replication factor is three, HDFS’s
placement policy is to put one replica on the local machine if the writer
is on a datanode, otherwise on a random datanode, another replica on a
node in a different (remote) rack, and the last on a different node in
the same remote rack. This policy cuts the inter-rack write traffic which
generally improves write performance. The chance of rack failure is far
less than that of node failure; this policy does not impact data
reliability and availability guarantees. However, it does reduce the
aggregate network bandwidth used when reading data since a block is
placed in only two unique racks rather than three. With this policy, the
replicas of a file do not evenly distribute across the racks. One third
of replicas are on one node, two thirds of replicas are on one rack, and
the other third are evenly distributed across the remaining racks. This
policy improves write performance without compromising data reliability
or read performance.

(2) Descripción del código fuente
Crtl + n para encontrar BlockPlacementPolicyDefault, busque el método chooseTargetInOrder en esta clase.
2) Selección de nodo de réplica Hadoop3.1.3
inserte la descripción de la imagen aquí

4.2 Proceso de lectura de datos HDFS

inserte la descripción de la imagen aquí
(1) El cliente solicita a NameNode que descargue el archivo a través de DistributedFileSystem, y NameNode encuentra la dirección de DataNode donde se encuentra el bloque de archivos consultando los metadatos.
(2) Seleccione un servidor DataNode (principio de proximidad, luego aleatorio) y solicite la lectura de datos.
(3) DataNode comienza a transmitir datos al cliente (lee el flujo de entrada de datos del disco y verifica las unidades del paquete).
(4) El cliente recibe paquetes en unidades de paquetes, primero los almacena en caché localmente y luego los escribe en el archivo de destino.

Cinco, NameNode y SecondaryNameNode

5.1 Mecanismo de trabajo de NN y 2NN

Pensando: ¿Dónde se almacenan los metadatos en el NameNode?

En primer lugar, supongamos que si se almacena en el disco del nodo NameNode, debido a que a menudo necesita acceso aleatorio y responde a las solicitudes de los clientes, debe ser demasiado ineficiente. Por lo tanto, los metadatos deben almacenarse en la memoria. Pero si solo existe en la memoria, una vez que se apague, los metadatos se perderán y todo el clúster no funcionará. Por lo tanto, produce una FsImage que realiza una copia de seguridad de los metadatos en el disco.

Esto traerá nuevos problemas, cuando se actualizan los metadatos en la memoria, si se actualiza el FsImage al mismo tiempo, la eficiencia será demasiado baja, pero si no se actualiza, se producirá el problema de consistencia. apagado, se producirá la pérdida de datos. Por lo tanto, se introduce el archivo Edits (solo se realizan operaciones de adición, lo cual es muy eficiente). Cada vez que se actualizan los metadatos o se agregan metadatos, los metadatos en la memoria se modifican y se agregan a las ediciones. De esta forma, una vez que se apaga el nodo NameNode, los metadatos se pueden sintetizar mediante la combinación de FsImage y Edits.

Sin embargo, si agrega datos a Edits durante mucho tiempo, los datos del archivo serán demasiado grandes y la eficiencia se reducirá, y una vez que se corte la energía, llevará demasiado tiempo restaurar los metadatos. Por lo tanto, es necesario fusionar periódicamente FsImage y Edits. Si el nodo NameNode completa esta operación, la eficiencia será demasiado baja. Por lo tanto, se introduce un nuevo nodo SecondaryNamenode, que se usa especialmente para fusionar FsImage y Edits.
inserte la descripción de la imagen aquí
1) La primera etapa: inicio de NameNode
(1) Después de iniciar NameNode por primera vez y formatear, cree archivos Fsimage y Edits. Si no es la primera vez que comienza, cargue directamente el registro de edición y el archivo espejo en la memoria.
(2) El cliente solicita agregar, eliminar o modificar metadatos.
(3) NameNode registra el registro de operaciones y actualiza el registro continuo.
(4) NameNode agrega, elimina y modifica metadatos en la memoria.
2) La segunda etapa: trabajo de NameNode secundario
(1) NameNode secundario le pregunta a NameNode si necesita CheckPoint. Ya sea para recuperar directamente el NameNode para verificar el resultado.
(2) Solicitudes secundarias de NameNode para ejecutar CheckPoint.
(3) NameNode desplaza el registro de ediciones que se está escribiendo.
(4) Copie el registro de edición y el archivo espejo antes de pasar al NameNode secundario.
(5) El NameNode secundario carga el registro de edición y el archivo espejo en la memoria y los fusiona.
(6) Genere un nuevo archivo de imagen fsimage.chkpoint.
(7) Copie fsimage.chkpoint en NameNode.
(8) NameNode cambia el nombre de fsimage.chkpoint a fsimage.

5.2 Análisis de Fsimage y ediciones


Después de formatear el concepto NameNode de Fsimage y Edits , se generarán los siguientes archivos en el directorio /opt/module/hadoop3.1.3/data/tmp/dfs/name/current

fsimage_0000000000000000000
fsimage_0000000000000000000.md5
seen_txid
VERSIÓN

(1) Archivo Fsimage: un punto de control permanente de metadatos del sistema de archivos HDFS, que contiene información de serialización de todos los directorios e inodos de archivos del sistema de archivos HDFS.
(2) Archivo de ediciones: la ruta para almacenar todas las operaciones de actualización del sistema de archivos HDFS.Todas las operaciones de escritura realizadas por el cliente del sistema de archivos se registrarán primero en el archivo de ediciones.
(3) El archivo seen_txid guarda un número, que es el número de las últimas ediciones_
(4) Cada vez que se inicia NameNode, el archivo Fsimage se leerá en la memoria y se cargará la operación de actualización en Edits para garantizar que La información de metadatos en la memoria es La más reciente y sincronizada se puede ver como la fusión de los archivos Fsimage y Edits cuando se inicia NameNode.

1) oiv ver el archivo Fsimage
(1) ver los comandos oiv y oev

[xusheng@hadoop102 current]$ hdfs
oiv      apply the offline fsimage viewer to an fsimage
oev      apply the offline edits viewer to an edits file

(2) Gramática básica

hdfs oiv -p 文件类型 -i 镜像文件 -o 转换后文件输出路径

(3) Práctica de casos

[xusheng@hadoop102 current]$ pwd
/opt/module/hadoop-3.1.3/data/dfs/name/current
[xusheng@hadoop102 current]$ hdfs oiv -p XML -i fsimage_0000000000000000025 -o /opt/module/hadoop-3.1.3/fsimage.xml
[xusheng@hadoop102 current]$ cat /opt/module/hadoop-3.1.3/fsimage.xml

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Copie el contenido del archivo xml que se muestra en el archivo xml creado en Idea y formatéelo. Algunos de los resultados mostrados son los siguientes.

<inode>
	<id>16386</id>
	<type>DIRECTORY</type>
	<name>user</name>
	<mtime>1512722284477</mtime>
	<permission>xusheng:supergroup:rwxr-xr-x</permission>
	<nsquota>-1</nsquota>
	<dsquota>-1</dsquota>
</inode>
<inode>
	<id>16387</id>
	<type>DIRECTORY</type>
	<name>xusheng</name>
	<mtime>1512790549080</mtime>
	<permission>xusheng:supergroup:rwxr-xr-x</permission>
	<nsquota>-1</nsquota>
	<dsquota>-1</dsquota>
</inode>
<inode>
	<id>16389</id>
	<type>FILE</type>
	<name>wc.input</name>
	<replication>3</replication>
	<mtime>1512722322219</mtime>
	<atime>1512722321610</atime>
	<perferredBlockSize>134217728</perferredBlockSize>
	<permission>xusheng:supergroup:rw-r--r--</permission>
	<blocks>
		<block>
			<id>1073741825</id>
			<genstamp>1001</genstamp>
			<numBytes>59</numBytes>
		</block>
	</blocks>
</inode >

Reflexionando: Se puede ver que no hay ningún DataNode correspondiente al bloque de registro en Fsimage, ¿por qué?
Una vez que se inicia el clúster, se requiere que DataNode informe la información del bloque de datos y que vuelva a informar después de un período de tiempo.
2) oev Ver archivo de ediciones
(1) Sintaxis básica

hdfs oev -p 文件类型 -i 编辑日志 -o 转换后文件输出路径

(2) Práctica de casos

[xusheng@hadoop102 current]$ hdfs oev -p XML -i edits_0000000000000000012-0000000000000000013 -o /opt/module/hadoop-3.1.3/edits.xml
[xusheng@hadoop102 current]$ cat /opt/module/hadoop-3.1.3/edits.xml

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Copie el contenido del archivo xml que se muestra en el archivo xml creado en Idea y formatéelo. Los resultados mostrados son los siguientes.

<?xml version="1.0" encoding="UTF-8"?>
<EDITS>
	<EDITS_VERSION>-63</EDITS_VERSION>
	<RECORD>
		<OPCODE>OP_START_LOG_SEGMENT</OPCODE>
		<DATA>
			<TXID>129</TXID>
		</DATA>
	</RECORD>
	<RECORD>
		<OPCODE>OP_ADD</OPCODE>
		<DATA>
			<TXID>130</TXID>
			<LENGTH>0</LENGTH>
			<INODEID>16407</INODEID>
			<PATH>/hello7.txt</PATH>
			<REPLICATION>2</REPLICATION>
			<MTIME>1512943607866</MTIME>
			<ATIME>1512943607866</ATIME>
			<BLOCKSIZE>134217728</BLOCKSIZE>
			<CLIENT_NAME>DFSClient_NONMAPREDUCE_-1544295051_1</CLIENT_NAME>
			<CLIENT_MACHINE>192.168.10.102</CLIENT_MACHINE>
			<OVERWRITE>true</OVERWRITE>
			<PERMISSION_STATUS>
				<USERNAME>xusheng</USERNAME>
				<GROUPNAME>supergroup</GROUPNAME>
				<MODE>420</MODE>
			</PERMISSION_STATUS>
			<RPC_CLIENTID>908eafd4-9aec-4288-96f1-e8011d181561</RPC_CLIENTID>
			<RPC_CALLID>0</RPC_CALLID>
		</DATA>
	</RECORD>
	<RECORD>
		<OPCODE>OP_ALLOCATE_BLOCK_ID</OPCODE>
		<DATA>
			<TXID>131</TXID>
			<BLOCK_ID>1073741839</BLOCK_ID>
		</DATA>
	</RECORD>
	<RECORD>
		<OPCODE>OP_SET_GENSTAMP_V2</OPCODE>
		<DATA>
			<TXID>132</TXID>
			<GENSTAMPV2>1016</GENSTAMPV2>
		</DATA>
	</RECORD>
	<RECORD>
		<OPCODE>OP_ADD_BLOCK</OPCODE>
		<DATA>
			<TXID>133</TXID>
			<PATH>/hello7.txt</PATH>
			<BLOCK>
				<BLOCK_ID>1073741839</BLOCK_ID>
				<NUM_BYTES>0</NUM_BYTES>
				<GENSTAMP>1016</GENSTAMP>
		</BLOCK>
		<RPC_CLIENTID></RPC_CLIENTID>
		<RPC_CALLID>-2</RPC_CALLID>
	</DATA>
	</RECORD>
	<RECORD>
		<OPCODE>OP_CLOSE</OPCODE>
		<DATA>
			<TXID>134</TXID>
			<LENGTH>0</LENGTH>
			<INODEID>0</INODEID>
			<PATH>/hello7.txt</PATH>
			<REPLICATION>2</REPLICATION>
			<MTIME>1512943608761</MTIME>
			<ATIME>1512943607866</ATIME>
			<BLOCKSIZE>134217728</BLOCKSIZE>
			<CLIENT_NAME></CLIENT_NAME>
			<CLIENT_MACHINE></CLIENT_MACHINE>
			<OVERWRITE>false</OVERWRITE>
			<BLOCK>
				<BLOCK_ID>1073741839</BLOCK_ID>
				<NUM_BYTES>25</NUM_BYTES>
				<GENSTAMP>1016</GENSTAMP>
			</BLOCK>
			<PERMISSION_STATUS>
				<USERNAME>xusheng</USERNAME>
				<GROUPNAME>supergroup</GROUPNAME>
				<MODE>420</MODE>
			</PERMISSION_STATUS>
		</DATA>
	</RECORD>
</EDITS >

Pensando: ¿Cómo determina NameNode qué ediciones fusionar en el próximo inicio?

5.3 Configuración de la hora del punto de control

1) Normalmente, SecondaryNameNode se ejecuta cada hora.
[hdfs-predeterminado.xml]

<property>
	<name>dfs.namenode.checkpoint.period</name>
	<value>3600s</value>
</property>

2) El número de operaciones se comprueba una vez por minuto, y cuando el número de operaciones llega a 1 millón, SecondaryNameNode lo ejecuta una vez.

<property>
	<name>dfs.namenode.checkpoint.txns</name>
	<value>1000000</value>
<description>操作动作次数</description>
</property>
<property>
	<name>dfs.namenode.checkpoint.check.period</name>
	<value>60s</value>
<description> 1 分钟检查一次操作次数</description>
</property>

6. Nodos de datos

6.1 Mecanismo de trabajo de DataNode

inserte la descripción de la imagen aquí

(1) Un bloque de datos se almacena en el disco en forma de archivo en el DataNode, incluidos dos archivos, uno son los datos en sí y el otro son metadatos que incluyen la longitud del bloque de datos, la suma de verificación de los datos del bloque y la marca de tiempo.
(2) DataNode se registra con NameNode después del inicio e informa toda la información del bloque a NameNode periódicamente (6 horas) después de pasar.

El intervalo de tiempo para que DN informe la información de interpretación actual a NN, el valor predeterminado es de 6 horas;

<property>
	<name>dfs.blockreport.intervalMsec</name>
	<value>21600000</value>
	<description>Determines block reporting interval in
milliseconds.</description>
</property>

El tiempo para que DN escanee su propia lista de información de bloqueo de nodos, el valor predeterminado es de 6 horas.

<property>
 	<name>dfs.datanode.directoryscan.interval</name>
	<value>21600s</value>
	<description>Interval in seconds for Datanode to scan data
directories and reconcile the difference between blocks in memory and on the disk.
	Support multiple time unit suffix(case insensitive), as described  in dfs.heartbeat.interval.
	</description>
</property>

(3) El latido del corazón es una vez cada 3 segundos, y el latido del corazón devuelve resultados con comandos de NameNode a DataNode
, como copiar datos de bloque a otra máquina o eliminar un determinado bloque de datos. Si no se recibe el latido de un DataNode durante más de 10 minutos, el nodo se considera no disponible.
(4) Es seguro unirse y salir de algunas máquinas durante el funcionamiento del clúster.

6.2 Integridad de los datos

Pensando: si los datos almacenados en el disco de la computadora son la señal de luz roja (1) y la señal de luz verde (0) que controlan la luz de señal del tren de alta velocidad, pero el disco que almacena los datos está roto y la luz verde siempre está encendida. mostrado, ¿es peligroso? Del mismo modo, si los datos en el nodo DataNode están dañados, pero no se encuentran, ¿también son peligrosos? Entonces, ¿cómo resolverlo?
El siguiente es el método del nodo DataNode para garantizar la integridad de los datos.
(1) Cuando DataNode lee Block, calculará CheckSum.
(2) Si el CheckSum calculado es diferente del valor cuando se creó el Bloque, significa que el Bloque ha sido dañado.
(3) El Cliente lee Bloques en otros Nodos de Datos.
(4) Algoritmos de verificación comunes crc (32), md5 (128), sha1 (160)
(5) DataNode verifica periódicamente CheckSum después de crear su archivo.
inserte la descripción de la imagen aquí

6.3 Parametrización del límite de tiempo de desconexión

Configuración del parámetro de límite de tiempo fuera de línea de DataNode
inserte la descripción de la imagen aquí
1. La muerte del proceso de DataNode o la falla de la red hace que DataNode no se comunique con NameNode
2. NameNode no considerará inmediatamente que el nodo está muerto, tomará un período de tiempo, este período se
denomina temporalmente período de tiempo de espera.
3. El tiempo de espera predeterminado de HDFS es de 10 minutos + 30 segundos.
4. Si el período de tiempo de espera se define como Tiempo de espera, la fórmula para calcular el período de tiempo de espera es:

TimeOut = 2 * dfs.namenode.heartbeat.recheck-interval + 10 *
dfs.heartbeat.interval。

El dfs.namenode.heartbeat.recheck-interval predeterminado es de 5 minutos y dfs.heartbeat.interval es de 3 segundos de forma predeterminada.
Tenga en cuenta que la unidad de heartbeat.recheck.interval en el archivo de configuración hdfs-site.xml es milisegundos y la unidad de dfs.heartbeat.interval es segundos .

<property>
	<name>dfs.namenode.heartbeat.recheck-interval</name>
	<value>300000</value>
</property>
<property>
	<name>dfs.heartbeat.interval</name>
	<value>3</value>
</property>

Supongo que te gusta

Origin blog.csdn.net/m0_52435951/article/details/124051951
Recomendado
Clasificación