Flink1.13新特性介绍

Flink1.13发布新特性

概要

这个版本是一些永久性的更新,帮助用户更好理解Flink程序的性能。当我们的流处理的速度并不是我们希望看到的性能的时候,这些新特性能帮助我们找到原因:数据加载和背压图能帮助定位性能瓶颈所在, CPU火焰图可以定位哪些代码是程序中的热点代码,State Access Latencies可以查看状态的保存情况

除了上述的特征,Flink社区还改进了系统的许多地方,其中有一些会在下面展示。

主要功能点

响应式伸缩

响应式伸缩是Flink的最新功能,它使流处理应用程序和其他应用程序一样自然,一样管理简单。

Flink的资源管理和部署具有双重特性,我们可以将Flink应用程序部署到K8S或者YARN等资源协调器上,这样Flink会积极管理和分配资源,并释放workers. 这对于快速修改Jobs或者Application的资源要求是非常有用的,比如批处理的应用或者ad-hoc的SQL查询。worker的数量将遵循Flink应用的并行度。

对于长时间运行的无限流程序,部署模式和其他长期运行的程序一样:应用程序不知道自己是运行在K8S,EKS或者YARN平台上,也不需要尝试获取一定数量的worker;相反,只需要提供给应用程序worker的数量,应用程序会根据提供的worker的数量自动调节并行度,我们称这种特性为响应式伸缩。

应用程序的部署模式开启了这项工作,类似于其他的程序部署一样(通过避开两个单独的步骤部署:1. 开启一个集群 2. 提交一个应用)。Flink的响应式伸缩模型完成了这点,使用者不需要使用额外的工具(脚本或者K8S命令)来保持worder的数量和程序的并行度的一致。

现在可以像对待其他典型应用程序一样,在Flink的应用程序中放一个自动伸缩器。同时在配置自动伸缩器的时候,你需要关心重新缩放的成本,因为有状态的流处理在伸缩的时候需要移动它的状态。

如果你需要尝试这个伸缩器的,需要添加scheduler-mode: reactive 这个配置到集群(只能是standalone 或者K8S集群)。详细参考

分析应用程序性能

和其他的程序一样,分析和理解Flink应用程序的性能是非常重要的。通常更关键的是,在了解性能的同时我们希望Flink能够在(近)实时延迟内提供结果,因为Flink应用程序通常是数据密集型的应用。

当程序处理的速度跟不上数据进来的速度,或者应用程序占用的资源超过了预期,下面的功能能帮助我们追踪到原因:

Bottleneck detection, Back Pressure monitoring

性能分析期间的第一个问题通常是:哪个Operation是瓶颈?

为了帮助回答这个问题,Flink公开了一些指标来描述那些当前处于繁忙或者背压状态的tasks的繁忙程度或者被压程度(背压是指有能力工作但不能工作,因为它们的后续操作符不能接受更多数据)。瓶颈所在都是那些繁忙的operators, 它们的上游operator实际承担大数据量的压力。

Flink 1.13带来了一个改进的背压度量系统(使用任务邮箱计时而不是线程堆栈采样),以及一个重新设计的作业数据流图形表示,用颜色编码和繁忙度和背压比率表示。

在这里插入图片描述

CPU flame graphs in Web UI

性能分析的第二个问题是:在所有有性能瓶颈的operators中,哪些operator的工作开销是最昂贵的?

回答这个问题,最直观的就是看CPU的火焰图:

  1. 当前哪些方法在消耗CPU的资源?
  2. 各个方法消耗的CPU的资源的多少对比?
  3. 堆栈上的哪些调用会导致执行特定的方法?

火焰图是跟踪堆栈线程然后重复多次采样而生成的。每个方法的调用都会有一个长方型表示,长方型的长度和它在采样中出现的次数成正比。启用后,可以在Operator UI上查看:
在这里插入图片描述

Access Latency Metrics for State

还有一个性能瓶颈的地方可能是backend state, 特别是当你的状态大小大于Flink当前可用的主内存并且你使用的是RockDB存储你的状态。

这并不是说RockDB慢,而是它在一定的条件下才能实现良好的性能。如果在云上使用了错误的硬盘资源类型,可有可能导致RockDB对磁盘IOPs的需求不足。

在CPU火焰图之上,新的后端状态延迟指标可以帮助解状态是否响应。e.g. 如果您看到RocksDB状态访问开始花费几毫秒的时间,可能需要查看您的内存和I/O配置。这些指标可以通过设置state.backend.rocksdb.latency-track-enabled可选项来激活使用。指标抽样收集应该对RocksDB状态后端性能有很小的影响。

Switching State Backend with savepoints

当需要从savepoint中回复Flink Job的时候,现在可以更改state backend。 这就意味着Flink的应用的状态不再锁定在程序最初启动时使用的状态了。e.g. 基于这个特性,我们可以在开始时使用HashMap来记录状态(纯粹在JVM中), 然后再状态增长太大的时候切换到RockDB来记录状态。

实际上,Flink现在有了规范的Savepoint格式,当为Savepoint创建数据快照时,所有状态后端都使用这种格式。

User-specified pod templates for Kubernetes deployments

在native K8S 部署模式下,用户可以指定pod模板。

使用这些模板,用户可以以Kubernetes-y的方式配置JobManagers和TaskManagers,其灵活性超出了直接内置到Flink的Kubernetes集成中的配置选项。

Unaligned Checkpoints - production-ready

非对齐的checkpoint可以在生产中使用了。如果你想在背压状态下看到程序的问题,鼓励使用unaligned checkpoints.

下面这些改变使unaligned checkpoints更容易使用:

  1. 在可以从unaligned checkpoints重新调整应用程序。如果您的应用程序由于无法(负担不起)创建Savepoints而需要从checkpoints进行扩展,那么这将非常方便
  2. 对于没有back-pressured的应用程序,启用unaligned checkpoints成本更低。unaligned checkpoints现在可以通过超时自适应地触发,这意味着一个checkpoint作为一个对齐的checkpoint开始(不存储任何飞行中的事件),并回落到一个未对齐的checkpoint(存储一些飞行中的事件),如果对齐阶段花费的时间超过了一定的时间.

Machine Learning Library moving to a separate repository

为了加快Flink机器学习(流、批处理和统一机器学习)的开发, 我们把主要经历放在Flink项目下的新库Flink-ml。在这里,我们遵循类似于Stateful Functions的方法,通过允许更多轻量级贡献工作流和单独的发布周期,单独的存储库帮助加快了开发。

请继续关注机器学习方面的更多更新,比如与ALink (Flink上许多常见的机器学习算法套件)的相互作用,或者Flink与TensorFlow的集成。

SQL和表的接口改进

与以前的版本一样,SQL和Table API仍然需求量最大的部分。

Windows via Table-valued functions 表值函数定义窗口

定义时间窗口是流SQL查询中最常见的操作之一。Flink 1.13介绍了一种定义窗口的新方法: 通过表值函数。这种方法不仅表达能力更强(允许您定义新的窗口类型),而且完全符合SQL标准。

Flink 1.13支持新的语法中的TUMBLE和HOP窗口,后续的版本中还会有SESSION窗口。为了演示增加的表达能力,考虑下面两个例子。

-- 一种新的 CUMULATE 窗函数,它给窗口分配一个扩展步长直到达到最大窗口大小:
SELECT window_time, window_start, window_end, SUM(price) AS total_price 
  FROM TABLE(CUMULATE(TABLE Bid, DESCRIPTOR(bidtime), INTERVAL '2' MINUTES, INTERVAL '10' MINUTES))
GROUP BY window_start, window_end, window_time;

可以引用表值窗口函数的窗口开始时间和窗口结束时间,从而使新类型的构造成为可能。除了常规的窗口聚合和窗口连接之外,现在可以表示窗口Top-K聚合:

SELECT window_time, ...
  FROM (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY window_start, window_end ORDER BY total_price DESC) 
      as rank 
    FROM t
  ) WHERE rank <= 100;

改进DataStream API和Table API/SQL之间的互操转换

这个版本从根本上简化了DataStream API和Table API程序的混合。Table API是开发应用程序的好方法,它具有声明特性和许多内置函数。 但有时需要转到使用DataStream API,以获得其表达性、灵活性和对状态的显式控制。

新的方法StreamTableEnvironment.toDataStream()/.fromDataStream() 从DataStream API创建一个DataStream作为表的Source或者Sink.

显著的改进有:

  1. DataStream和Table API类型自动类型转换
  2. Event Time配置的无缝集成; 为了高一致性,水印在边界流动
  3. 对Row类(表示来自Table API的行事件)的增强已经得到了重大改进(改进了toString()/hashCode()/equals()方法的行为),现在支持通过名称访问实例属性值,并支持稀疏表示。
Table table=tableEnv.fromDataStream(
	dataStream,Schema.newBuilder()
	.columnByMetadata("rowtime","TIMESTAMP(3)")
	.watermark("rowtime","SOURCE_WATERMARK()")
	.build());

DataStream<Row> dataStream=tableEnv.toDataStream(table)
	.keyBy(r->r.getField("user"))
	.window(...)

SQL Client: Init scripts and Statement Sets

SQL客户端是一种直接运行和部署SQL流作业和批处理作业的简便方法,不需要命令行编写代码,也不需要CI/CD的支持。

本版本改进了许多SQL客户端的功能,几乎Java应用中可以使用所有的operations都可以在SQL客户端或者SQL脚本中使用。也就是说SQL用户将写更少的代码。

Easier Configuration and Code Sharing 更简单的配置和代码共享

SQL客户端将停止对YAML文件的支持,转而在执行主SQL脚本前接受一个或者多个初始化脚本来配置session.

这些初始化的脚本通常在软对或者部署之间共享,可以用于加载公共的catalogs,应用公共配置设置或者定义标准视图。

./sql-client.sh -i init1.sql init2.sql -f sqljob.sql

更多的配置选项

一组更大的可识别配置选项和改进的set/RESET命令使得在SQL客户端和SQL脚本中定义和控制应用程序的执行变得更容易。

在一个上下文中支持多查询

支持在一个Flink Job中执行多个SQL语句查询,这对无限流中的SQL查询非常有用。

Statement Set是将应该放在一起执行的查询分组在一起的机制

下面是一个可以通过Flink SQL命令行客户端运行的SQL脚本例子。 它设置和配置环境并执行多个查询。 该脚本捕获端到端查询和所有环境构建和配置工作,使其成为自包含的artifact。

-- set up a catalog
CREATE CATALOG hive_catalog WITH ('type' = 'hive');
USE CATALOG hive_catalog;

-- or use temporary objects
CREATE TEMPORARY TABLE clicks (
  user_id BIGINT,
  page_id BIGINT,
  viewtime TIMESTAMP
) WITH (
  'connector' = 'kafka',
  'topic' = 'clicks',
  'properties.bootstrap.servers' = '...',
  'format' = 'avro'
);

-- set the execution mode for jobs
SET execution.runtime-mode=streaming;

-- set the sync/async mode for INSERT INTOs
SET table.dml-sync=false;

-- set the job's parallelism
SET parallism.default=10;

-- set the job name
SET pipeline.name = my_flink_job;

-- restore state from the specific savepoint path
SET execution.savepoint.path=/tmp/flink-savepoints/savepoint-bb0dab;

BEGIN STATEMENT SET;

INSERT INTO pageview_pv_sink
SELECT page_id, count(1) FROM clicks GROUP BY page_id;

INSERT INTO pageview_uv_sink
SELECT page_id, count(distinct user_id) FROM clicks GROUP BY page_id;

END;

Hive查询语法兼容性

现在可以使用Hive SQL语法编写针对Flink的SQL查询。 除了Hive的DDL方言,Flink现在也接受常用的Hive DML和DQL方言。

要使用Hive SQL方言,设置 table.sql-dialecthive并加载 HiveModuleHiveModule 的加载很重要,因为Hive的内置函数需要适当的语法和语义兼容性。 下面的例子说明了这一点:

CREATE CATALOG myhive WITH ('type' = 'hive'); -- setup HiveCatalog
USE CATALOG myhive;
LOAD MODULE hive; -- setup HiveModule
USE MODULES hive,core;
SET table.sql-dialect = hive; -- enable Hive dialect
SELECT key, value FROM src CLUSTER BY key; -- run some Hive queries

请注意,Hive方言不再支持Flink的SQL语法的DML和DQL语句, 需要切换回Flink语法的默认方言。

改进SQL时间函数的行为

处理时间是任何数据处理的关键要素。 但同时,处理包含不同的时区、日期和时间的数据时是一项非常精细的任务。

在Flink 1.13。 官方花了很多精力简化与时间相关的函数的使用。 调整了(更具体地)函数的返回类型,如 PROCTIME()CURRENT_TIMESTAMPNOW()

此外,您现在还可以在 TIMESTAMP_LTZ 列上定义event time属性,以便在Daylight Saving Time的支持下优雅地进行窗口处理。

PyFlink的改进

PyFlink这个版本的主要的主题是让Python DataStream API和Table API在特性上更接近Java/Scala API。

Python DataStream API中的有状态操作

在Flink 1.13中, Python程序员现在也可以充分享受Apache Flink的有状态流处理api的潜力。 Flink 1.12中引入的重新架构过的Python DataStream API,现在拥有完整的状态功能,允许用户记住状态中的事件的信息,并在以后对其进行操作。

这种有状态处理能力是许多更复杂的处理操作的基础,这些操作需要记住跨单个事件的信息(例如,Windowing operations)。

下面这个例子展示了一个自定义计数窗口的实现,使用state:

class CountWindowAverage(FlatMapFunction):
    def __init__(self, window_size):
        self.window_size = window_size

    def open(self, runtime_context: RuntimeContext):
        descriptor = ValueStateDescriptor("average", Types.TUPLE([Types.LONG(), Types.LONG()]))
        self.sum = runtime_context.get_state(descriptor)

    def flat_map(self, value):
        current_sum = self.sum.value()
        if current_sum is None:
            current_sum = (0, 0)
        # update the count
        current_sum = (current_sum[0] + 1, current_sum[1] + value[1])
        # if the count reaches window_size, emit the average and clear the state
        if current_sum[0] >= self.window_size:
            self.sum.clear()
            yield value[0], current_sum[1] // current_sum[0]
        else:
            self.sum.update(current_sum)

ds = ...  # type: DataStream
ds.key_by(lambda row: row[0]) \
  .flat_map(CountWindowAverage(5))

PyFlink DataStream API中用户自定义窗口

Flink 1.13为PyFlink DataStream API增加了对用户定义的窗口的支持。 Flink程序现在可以在标准窗口定义之外使用窗口。

因为窗口是所有处理无限流的程序的核心(通过将无限流分割成有大小的“桶”),这大大提高了API的表达能力。

PyFlink Table API中基于行的操作

Python Table API现在支持基于行的操作,例如,自定义的行转换函数。 这些函数是在内置函数之外对表应用数据转换的一种简单方法。

这是一个在Python Table API中使用map()操作的例子:

@udf(result_type=DataTypes.ROW(
  [DataTypes.FIELD("c1", DataTypes.BIGINT()),
   DataTypes.FIELD("c2", DataTypes.STRING())]))
def increment_column(r: Row) -> Row:
  return Row(r[0] + 1, r[1])

table = ...  # type: Table
mapped_result = table.map(increment_column)

除了map()之外,该API还支持flat_map()、aggregate()、flat_aggregate()和其他基于行操作的函数。 这使得Python Table API与Java Table API在特性上更相近了。

PyFlink DataStream程序的批处理执行模式

PyFlink DataStream API现在也支持有界流的批处理执行模式,这是在Flink 1.12中为Java DataStream API引入的。

批处理执行模式通过利用有界流的特性,绕过状态后端和检查点,简化了有界流上的操作并提高了程序的性能。

其他改进

使用Hugo查看Flink Documentation

Flink文档已经从Jekyll迁移到了Hugo。

Web UI中的历史异常

Flink Web UI将显示多个(n个)导致作业失败的异常。 这有助于调试由根故障导致后续故障的场景。 可以在异常历史记录中找到失败的根本原因。

更好的报告失败的checkpoints的异常或者失败的原因

Flink现在提供了失败或被中止的检查点的统计信息,以便更容易地确定失败原因,而不必分析日志

以前版本的Flink只有在检查点成功的情况下才会报告指标(例如,持久化数据的大小、触发时间)。

PyFlink Table API支持用户在Group Windows自定义聚合函数

PyFlink的Table API中的组窗口现在同时支持一般的Python用户定义聚合函数(udaf)和Pandas udaf。 这些功能对于许多分析和ML训练程序是至关重要的。

Flink 1.13对以前的版本进行了改进,在以前的版本中,这些函数只支持无界的Group-by聚合。

改进Batch Execution下的Sort-Merge Shuffle

Flink 1.13提高了批执行程序的内存稳定性和Sort-Merge Shuffle的性能,Flink 1.12最初是通过FLIP-148引入的。

具有更高并行度(1000秒)的程序应该不再频繁触发OutOfMemoryError: Direct Memory。 通过更好的I/O调度和广播优化提高了性能(特别是在旋转磁盘上)。

HBase连接器支持异步查找和查找缓存

HBase Lookup Table Source现在支持异步查找模式和查找缓存。 这极大地提高了对HBase进行查找连接的Table/SQL作业的性能,同时减少了典型场景下对HBase的I/O请求。

在以前的版本中,HBase Lookup Source只进行同步通信,导致管道利用率和吞吐量较低。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值