HDFS で多数の小さなファイルを圧縮

前回のファイル圧縮後に、次の 2 つの問題が発生しました。

  1. 一部のログはボリュームが大きく、1 日あたり 100G を超えるため、ftp を使用してローカルにデータを取得するには時間がかかりすぎるため、この方法はお勧めできません。
  2. Spark Streaming によりリアルタイムにログが収集されるため、データの分布が均一ではなく、大きなものは 5G、小さなものは数十 MB にすぎず、圧縮後も小さなファイルが多数存在します。 HDFS の読み取りパフォーマンスに大きな影響を与えます。

この状況に対しては、次の解決策が提供されます。

1. アーカイブ

データのこの部分を最初にアーカイブします。アーカイブすると、データ量を変更せずに多数の小さなファイルをマージできます。

元のデータがアーカイブされ
ここに画像の説明を挿入します
た後、
ここに画像の説明を挿入します
ここに画像の説明を挿入します
データは均等に分散されます。

2. 圧縮

データ量が大きいため、ftp 方式は推奨されないため、プログラムを使用して圧縮します。

/**
 * Created by wpq on 2019/3/27.
 * 压缩测试
 */
public class HdfsCompressTest {
    public static void main(String[] args) throws ClassNotFoundException, IOException {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("stattime:" + df.format(new Date()));
        Class<?> cal = Class.forName("org.apache.hadoop.io.compress.GzipCodec");
        Configuration conf = new Configuration();
        conf.set("fs.hdfs.impl", "org.apache.hadoop.hdfs.DistributedFileSystem");
        FileSystem fs = FileSystem.get(conf);
        CompressionCodec codec = (CompressionCodec) ReflectionUtils.newInstance(cal, conf);
        //指定压缩和被压缩的文件
        String inputfile = "/user/hdfs/rsync";
        //String inputfile = "/user/hdfs/wpq/tmp";
        RemoteIterator<LocatedFileStatus> files = fs.listFiles(new Path(inputfile), true);
        while (files.hasNext()) {
            LocatedFileStatus next = files.next();
            if (next.isFile()) {
                Path path = next.getPath();
                if (path.toString().endsWith("gz")) {
                } else {
                    //指定压缩输入流
                    FSDataInputStream in = fs.open(path);
                    //指定压缩输出流
                    String outfile = path.toString() + codec.getDefaultExtension();//添加压缩格式为后缀
                    FSDataOutputStream outputStream = fs.create(new Path(outfile));
                    CompressionOutputStream out = codec.createOutputStream(outputStream);
                    IOUtils.copyBytes(in, out, 4096, false);
                    in.close();
                    out.close();
                    fs.delete(path, true);
                }
            }
        }
        System.out.println("endtime:" + df.format(new Date()));
    }
}

3. 検証

毎月 1 日と 15 日のデータ 100 個とその日のデータの合計数を抽出し、比較して OK を確認し、元のデータを削除します。

おすすめ

転載: blog.csdn.net/qq_42264264/article/details/88885740