相关文章推荐

最近有一个需求,就是定时去统计,hdfs上的文件的大小和行数,也就是统计这段时间内新增的数据的条数和占用空间。
举个例子:一天24小时,每6个小时统计一次,这6个小时内,新增了多少条数据,以及这些数据在hdfs上占用了多少空间。

一些配置和前提说明

hadoop的一些说明

在这里,假设hdfs上的文件没有任何压缩格式,且hdfs中的数据是整齐无缺损的,其中存在用来筛选的时间字段。
举个例子:

1	159298900	15
2	159298900	45
3	159298901	12
.......

      这里的第一个字段和第三个字段不用管,第二个字段是表示数据的时间的,不过要注意,这个字段表示的是秒还是毫秒

代码的一些说明

      这里无论你是用java还是scala,都不影响。
      就我个人涉及到的知识面而言,无非就是java的FileSystem,以及spark的textFile。所以这个说明其实就是:如何用FileSystem或spark读取hdfs的数据。
      这个在这写太麻烦了,请看下面的链接:
      
java 使用FileSystem读取hadoop文件
      使用spark读取hadoop文件的具体内容
      

pom.xml

<dependencies>
	<dependency>
	    <groupId>org.apache.hive</groupId>
	    <artifactId>hive-jdbc</artifactId>
	    <version>2.1.1</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.hadoop</groupId>
	    <artifactId>hadoop-client</artifactId>
	    <version>3.0.0</version>
	</dependency>
	<dependency>
	    <groupId>org.apache.hadoop</groupId>
	    <artifactId>hadoop-common</artifactId>
	    <version>3.0.0</version>
	</dependency>
</dependencies>

使用FileSystem获取文件行数

      这种方法的步骤是:读取hadoop文件,统计行数,没啥难度。

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
public class testNewFile {
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        FileSystem fs=FileSystem.get(
            new URI( "hdfs://172.0.0.1:9000"), new Configuration(), "root");
        FSDataInputStream in = fs.open(
        	new Path( "hdfs://172.0.0.1:9000/user/hive/warehouse/test.db/t1/dt=3/t1"));
        BufferedReader d = new BufferedReader(new InputStreamReader(in));
        long count = 0;
        String line;
        while ((line = d.readLine()) != null) {
            count += 1L;
        System.out.println( count );
        d.close();
        in.close();
        fs.close();

使用spark获取hdfs 文件的条数

      习惯用scala了,所以这里也用Scala了。

import org.apache.spark.{SparkConf, SparkContext} * Created by admin on 2020/7/3. object test01 { def main(args: Array[String]): Unit = { val conf = new SparkConf().setAppName("test").setMaster("local[*]") val sc = new SparkContext(conf) val hadoopRdd = sc.textFile( "hdfs://172.0.0.1:9000/user/hive/warehouse/test.db/t1/dt=3/t1" println(hadoopRdd.count())

第一种解决办法:使用getBytes()

      这个其实也是最笨的一个方法,把每条数据读出来,然后value.getBytes().length,就可以获取到当前这一行数据的大小。
      具体代码如下:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
public class test {
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        FileSystem fs=FileSystem.get(
            new URI( "hdfs://172.0.0.1:9000"), new Configuration(), "root");
        FSDataInputStream in = fs.open(
        	new Path




    
( "hdfs://172.0.0.1:9000/user/hive/warehouse/test.db/t1/dt=3/t1"));
        BufferedReader d = new BufferedReader(new InputStreamReader(in));
        long count = 0;
        long store = 0;
        String line;
        while ((line = d.readLine()) != null) {
            count += 1L;
            store += line.getBytes().length;
        System.out.println( count );
        System.out.println( store );
        d.close();
        in.close();
        fs.close();

第二种解决办法:使用listStatus()

      hadoop的jar包里,有这么个api,可以获取一个路径下所有文件、文件夹的状态。这个状态,其中就包含了block的数量,以及文件大小。

简单的情况

      假设该文件夹下面全都是文件,没有文件夹套文件夹套文件的情况。
      代码如下:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class test {
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        FileSystem fs=FileSystem.get(
                new URI("hdfs://127.0.0.1:9000"), new Configuration(), "root");
        FileStatus[] in = fs.listStatus(new Path(
                "hdfs://127.0.0.1:9000/user/hive/warehouse/test.db/t1/dt=3"));
        System.out.println( in[0].getLen() );
        fs.close();

      因为我知道我这一个文件夹底下只有一个文件,所以我in[0]就完事了。如果一个文件夹下面有N多文件,则需要循环遍历,且相加。

比较麻烦的情况

      这种方法虽然简单,但是最好文件夹下面就全是文件,不要文件夹下面还有文件夹,然后还有文件。也就是说,这种方法不太适合于文件夹下面还有文件夹的情况。
      不是说处理不了,而是如果变成了文件夹下面有N层的话,你就得像统计一个文件夹有多大那样写递归了…很麻烦。

        FileStatus[] in = fs.listStatus(
                new Path( "hdfs://172.0.0.1:9000/user/hive/warehouse/test.db/t1/dt=3"));
        System.out.println( in[0].getLen() );
        System.out.println( in[0].isDirectory() );
        System.out.println( in[0].isFile() );

      有 isDirectory()isFile()方法,递归也可以算出来,但是太麻烦了,想写自己写吧,我这里就不写了…

第三种解决办法:使用getContentSummary()

      上述的那种麻烦的情况,可以使用这种方法来解决。
      hadoop的jar包里,有这么个api,可以获取一个文件夹下,文件的数量,文件夹的数量,以及这个文件夹的大小。不过我只关心这个文件夹的大小,其他的不关心。
      代码如下:

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.ContentSummary;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class test {
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        FileSystem fs=FileSystem.get(
                new URI("hdfs://172.0.0.1:9000"), new Configuration(), "root");
        ContentSummary in = fs.getContentSummary(new Path(
                "hdfs://172.0.0.1:9000/user/hive/warehouse/test.db/t1/dt=3"));
        System.out.println( in.getLength() );
        fs.close();

      这样就可以直接获取文件夹的大小了,不用考虑递归什么的了。

额外说点hadoop fs -dus

      这个命令就是显示文件的大小。

[root@Sla2 ~]# hdfs dfs -dus /tmp/root/
dus: DEPRECATED: Please use 'du -s' instead.
4217122515  /tmp/root/

       hadoop fs -dus 的源码:

public static void dus(String src,Configuration conf) throws IOException {
	    Path srcPath = new Path(src);
	    FileSystem srcFs = srcPath.getFileSystem(conf);
	    FileStatus status[] = srcFs.globStatus(new Path(src));
	    if (status==null || status.length==0) {
	      throw new FileNotFoundException("Cannot access " + src + 
	          ": No such file or directory.");
	    for(int i=0; i<status.length; i++) {
	      long totalSize = srcFs.getContentSummary(status[i].getPath()).getLength();
	      String pathStr = status[i].getPath().toString();
	      System.out.println(("".equals(pathStr)?".":pathStr) + "\t" + totalSize);

       看到里面的getContentSummary()了么

文章目录一些配置和前提说明hadoop的一些说明代码的一些说明pom.xml获取行数使用FileSystem获取文件行数使用spark获取hdfs 文件的条数获取大小第一种解决办法:使用getBytes()第二种解决办法:使用listStatus()简单的情况比较麻烦的情况第三种解决办法:使用getContentSummary()额外说点hadoop fs -dus &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb
查看表的大小通常的方法是hdfs dfs -du -h, 但统计的是子目录的大小,如: hdfs dfs -du -h /user/hive/warehouse/tmp.db/xxx 555.7 G 1.6 T /user/hive/warehouse/tmp.db/xxx/data_date=20200610 556.2 G 1.6 T /user/hive/warehouse/tmp.db/xxxt/data_date=20200611 其实我们需要统计当前目录的大小时可加入 -s
前面博客里面提到,运行一次hadoop的时候出现java heap error。字面意思分配堆的时候出现错误,我们知道应用程序的动态内存的分配均在堆里面。这里提示堆错误,那必然是内存不够用了。那么这个namenode内存的大小该怎么取值呢? namenode管理着集群里面所有文件的信息。简单根据文件信息给出一个准确计算内存大小的公式是不现实的。 hadoop默认namenode内存的大小为10
Hive、HadoopSpark都是大数据领域常用的工具。 Hive是一个基于Hadoop数据仓库工具,它提供了类似SQL的查询语言,可以将结构化的数据存储在Hadoop分布式文件系统,并通过Hive查询数据Hadoop是一个分布式计算框架,它可以处理大规模数据集并提供高可靠性、高可扩展性和高性能的数据存储和处理能力。Hadoop包括HDFSHadoop分布式文件系统)和MapReduce计算框架。 Spark是一个快速、通用、可扩展的大数据处理引擎,它可以在内存执行数据处理任务,比Hadoop的MapReduce更快。Spark支持多种编程语言,包括JavaScala和Python等。 在实际应用,Hive、HadoopSpark通常会结合使用,以实现更高效、更灵活的大数据处理和分析。