6.1. Les données Flink sont écrites dans le fichier

1. Introduction

L'API Flink fournit le connecteur FileSink pour nous aider à écrire des données sur le système de fichiers

Notes de version : java1.8, flink1.17

Lien du site officiel : site officiel


2. Types de format - Spécifiez le format de fichier

FileSink Prend en charge les formats codés en ligne et en bloc pour l'écriture dans le système de fichiers

        Encodage en ligne : format texte

        Encodage en masse : Parquet, Avro, SequenceFile, Compress, Orc

Row-encoded sink: FileSink.forRowFormat(basePath, rowEncoder)
Bulk-encoded sink: FileSink.forBulkFormat(basePath, bulkWriterFactory)

3. Stratégie de partition de fichier d'allocation de compartiment (sous-répertoire)

La logique du compartiment définit la manière dont les données sont distribuées dans les sous-répertoires du répertoire de sortie de base. (Comme les partitions dans Hive)

Flink dispose de deux stratégies d'allocation intégrées :

  • DateTimeBucketAssigner : Allocateur temporel par défaut
  • BasePathBucketAssigner : alloue tous les fichiers à stocker sur le chemin de base (un seul compartiment global)
BasePathBucketAssigner - ne génère pas de sous-répertoires
DateTimeBucketAssigner - regroupement basé sur le temps

Exemple de code :

// TODO 按照时间进行分桶,每分钟生成一个子目录,目录名称为 yyyy-MM-dd HH-mm
.withBucketAssigner(new DateTimeBucketAssigner<>("yyyy-MM-dd HH-mm", ZoneId.systemDefault()))
// TODO 当个全局桶,不生成子目录
.withBucketAssigner(new BasePathBucketAssigner())

4. Roulement de fichiers divisés par stratégie

La politique continue définit « quand générer de nouveaux fichiers », qui peut être configuré en spécifiant l'heure de création et la taille du fichier.

// TODO 文件滚动策略:  文件创建后1分钟 或 大小超过1m 时生成新的文件
.withRollingPolicy(
    DefaultRollingPolicy.builder()
            .withRolloverInterval(Duration.ofMinutes(1))     //   指定文件持续时间
            .withMaxPartSize(new MemorySize(1024 * 1024))    //   指定文件大小
            .build()
)

5. Nommage des fichiers et cycle de vie

Les fichiers pièce peuvent être dans l'un des trois états suivants :

  1. En cours  : Le fichier pièce en cours d'écriture est à l'état En cours
  2. En attente : fermez le fichier d'état en cours en raison de la stratégie de roulement spécifiée et attendez la soumission.
  3. TerminéSTREAMING : Un point de contrôle réussi en  mode streaming ( ) ou BATCHla fin de la saisie en mode batch (), et le statut En attente du fichier est converti en statut Terminé.

Remarque :  La fonction de point de contrôle doit être activée STREAMING pour pouvoir être utilisée en mode  FileSink . Les fichiers au statut Terminé ne sont générés que lorsque Checkpoint réussit. Si la fonction Checkpoint n'est pas activée, le fichier restera toujours dans  in-progress l'état ou  pending et le système en aval ne pourra pas lire les données du fichier en toute sécurité.

Stratégie de dénomination des fichiers :

  • En cours / En attente:prefix-part-<uid>-<partFileIndex>.ext.inprogress.uid
  • Terminé:préfixe-part-<uid>-<partFileIndex>.ext

    préfixe : préfixe du nom de fichier (la valeur par défaut est vide)

  ext :文件名称后缀(默认为空)

  uid :uid est une valeur d'ID aléatoire attribuée à la sous-tâche

└── 2019-08-25--12
    ├── prefix-4005733d-a830-4323-8291-8866de98b582-0.ext
    ├── prefix-4005733d-a830-4323-8291-8866de98b582-1.ext.inprogress.bd053eb0-5ecf-4c85-8433-9eff486ac334
    ├── prefix-81fc4980-a6af-41c8-9937-9939408a734b-0.ext
    └── prefix-81fc4980-a6af-41c8-9937-9939408a734b-1.ext.inprogress.bc279efe-b16f-47d8-b828-00ef6e2fbd11

Exemple de code :

// TODO 指定输出文件的名称配置 前缀、后缀
.withOutputFileConfig(
    OutputFileConfig.builder()
            .withPartPrefix("flink") // 指定前缀
            .withPartSuffix("txt")   // 指定后缀
            .build()
)

6. Ceci est un exemple complet

package com.baidu.datastream.sink;

import org.apache.flink.api.common.serialization.SimpleStringEncoder;
import org.apache.flink.configuration.MemorySize;
import org.apache.flink.connector.file.sink.FileSink;
import org.apache.flink.core.fs.Path;
import org.apache.flink.streaming.api.CheckpointingMode;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.sink.filesystem.OutputFileConfig;
import org.apache.flink.streaming.api.functions.sink.filesystem.bucketassigners.DateTimeBucketAssigner;
import org.apache.flink.streaming.api.functions.sink.filesystem.rollingpolicies.DefaultRollingPolicy;

import java.time.Duration;
import java.time.ZoneId;

// TODO flink 数据输出到文件系统
public class SinkFiles {
    public static void main(String[] args) throws Exception {
        // 1.获取执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(2);

        // STREAMING 模式时,必须开启checkpoint,否则文件一直都是 .inprogress
        env.enableCheckpointing(2000, CheckpointingMode.EXACTLY_ONCE);

        // 2.指定数据源
        DataStreamSource<String> streamSource = env.socketTextStream("localhost", 9999);

        // 3.初始化 FileSink 实例
        FileSink<String> fileSink = FileSink
                // TODO 指定输出方式 行式输出、文件路径、编码
                .<String>forRowFormat(new Path("data/output"), new SimpleStringEncoder<String>("UTF-8"))
                // TODO 指定输出文件的名称配置 前缀、后缀
                .withOutputFileConfig(
                        OutputFileConfig.builder()
                                .withPartPrefix("flink") // 指定前缀
                                .withPartSuffix(".txt")   // 指定后缀
                                .build()
                )
                // TODO 按照时间进行目录分桶:每分钟生成一个目录,目录格式为 yyyy-MM-dd HH-mm
                .withBucketAssigner(new DateTimeBucketAssigner<>("yyyy-MM-dd HH-mm", ZoneId.systemDefault()))
                // TODO 文件滚动策略:  1分钟 或 1m 生成新的文件
                .withRollingPolicy(
                        DefaultRollingPolicy.builder()
                                .withRolloverInterval(Duration.ofMinutes(1))
                                .withMaxPartSize(new MemorySize(1024 * 1024))
                                .build()
                )
                .build();

        streamSource.sinkTo(fileSink);

        // 3.触发程序执行
        env.execute();
    }
}

おすすめ

転載: blog.csdn.net/weixin_42845827/article/details/132835352