【问题标题】:Why does Flink FileSystem sink splits into multiple files为什么 Flink FileSystem sink 拆分成多个文件
【发布时间】:2021-06-12 12:45:54
【问题描述】:

我想使用 Flink 从输入文件中读取数据,进行一些聚合,然后将结果写入输出文件。作业处于批处理模式。请参阅下面的wordcount.py

from pyflink.table import EnvironmentSettings, BatchTableEnvironment

# https://ci.apache.org/projects/flink/flink-docs-release-1.12/dev/python/table_api_tutorial.html

env_settings = EnvironmentSettings.new_instance().in_batch_mode().build()
table_env = BatchTableEnvironment.create(environment_settings=env_settings)

my_source_ddl = """
    create table mySource (
        word VARCHAR
    ) with (
        'connector' = 'filesystem',
        'format' = 'csv',
        'path' = '/tmp/input'
    )
"""

my_sink_ddl = """
    create table mySink (
        word VARCHAR,
        `count` BIGINT
    ) with (
        'connector' = 'filesystem',
        'format' = 'csv',
        'path' = '/tmp/output'
    )
"""

transform_dml = """
INSERT INTO mySink
SELECT word, COUNT(1) FROM mySource GROUP BY word
"""

table_env.execute_sql(my_source_ddl)
table_env.execute_sql(my_sink_ddl)
table_env.execute_sql(transform_dml).wait()

# before run: echo -e  "flink\npyflink\nflink" > /tmp/input
# after run: cat /tmp/output

在运行python wordcount.py 之前,我运行echo -e "flink\npyflink\nflink" > /tmp/input 以确保数据存在于/tmp/input 中。但是运行之后,/tmp/output 里面有两个文件:

> ls /tmp/output
part-305680d0-e680-420f-ab17-3e558ceaeba3-cp-0-task-6-file-0 part-305680d0-e680-420f-ab17-3e558ceaeba3-cp-0-task-7-file-0
> cat /tmp/output/part-305680d0-e680-420f-ab17-3e558ceaeba3-cp-0-task-6-file-0
pyflink,1
> cat /tmp/output/part-305680d0-e680-420f-ab17-3e558ceaeba3-cp-0-task-7-file-0
flink,2

虽然我期望单个文件 /tmp/output 包含内容:

pyflink,1
flink,2

实际上,我通过调整下面的生成单个文件/tmp/output的python程序得到了上面的python程序。

from pyflink.dataset import ExecutionEnvironment
from pyflink.table import TableConfig, DataTypes, BatchTableEnvironment
from pyflink.table.descriptors import Schema, OldCsv, FileSystem
from pyflink.table.expressions import lit

# https://ci.apache.org/projects/flink/flink-docs-release-1.12/dev/python/table_api_tutorial.html

exec_env = ExecutionEnvironment.get_execution_environment()
exec_env.set_parallelism(1)
t_config = TableConfig()
t_env = BatchTableEnvironment.create(exec_env, t_config)

t_env.connect(FileSystem().path('/tmp/input')) \
    .with_format(OldCsv()
                 .field('word', DataTypes.STRING())) \
    .with_schema(Schema()
                 .field('word', DataTypes.STRING())) \
    .create_temporary_table('mySource')

t_env.connect(FileSystem().path('/tmp/output')) \
    .with_format(OldCsv()
                 .field_delimiter('\t')
                 .field('word', DataTypes.STRING())
                 .field('count', DataTypes.BIGINT())) \
    .with_schema(Schema()
                 .field('word', DataTypes.STRING())
                 .field('count', DataTypes.BIGINT())) \
    .create_temporary_table('mySink')

tab = t_env.from_path('mySource')
tab.group_by(tab.word) \
   .select(tab.word, lit(1).count) \
   .execute_insert('mySink').wait()

运行此版本将生成 /tmp/output。请注意,它不带有逗号分隔符。

> cat /tmp/output
flink   2
pyflink 1

知道为什么吗?谢谢!

【问题讨论】:

    标签: apache-flink pyflink


    【解决方案1】:

    您第一次运行它时没有指定并行度,因此您得到了默认的并行度 - 大于 1(可能是 4 或 8,取决于您的计算机有多少内核)。

    Flink 被设计成可扩展的,为了实现这一点,一个算子的并行实例(例如接收器)相互解耦。例如,想象一下具有 100 或 1000 多个节点的大型集群。为了使其正常工作,每个实例都需要写入自己的文件。

    逗号已更改为制表符,因为您指定了.field_delimiter('\t')

    【讨论】:

    • 嗨大卫,是的,将默认并行度设置为 1 (table_env.get_config().get_configuration().set_string("parallelism.default", "1")) 将输出文件的数量减少到 1,并且内容是预期的,但它仍然带有一个长名称并位于 / tmp/output,而不是 /tmp/output 文件本身。我想知道为什么。谢谢
    • 该接口旨在支持批处理和流式管道。为了支持流用例,有必要有一种方法来命名可以无限期运行的输出文件 - 即多年 - 以非常高的容量运行,例如每天 PB。
    猜你喜欢
    • 1970-01-01
    • 2021-10-29
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 2013-08-24
    • 1970-01-01
    • 2016-11-06
    • 2021-11-06
    相关资源
    最近更新 更多