外部数据访问的异步 I/O
本页解释了使用 Flink 的 API 进行异步 I/O 与外部数据存储。对于不熟悉异步或事件驱动编程的用户,一篇关于 Futures 和事件驱动编程的文章可能是有用的准备。
注意:有关异步 I/O 实用程序的设计和实现的详细信息,请参阅提案和设计文档 FLIP-12:异步 I/O 设计和实现。
需要异步 I/O 操作
在与外部系统交互时(例如,当使用存储在数据库中的数据丰富流事件时),需要注意与外部系统的通信延迟不会主导流应用程序的全部工作。
天真地访问外部数据库中的数据,例如在 a 中MapFunction,通常意味着同步交互:请求被发送到数据库并MapFunction等待直到收到响应。在许多情况下,这种等待占了函数时间的绝大部分。
与数据库的异步交互意味着单个并行函数实例可以同时处理多个请求并同时接收响应。这样,等待时间可以与发送其他请求和接收响应重叠。至少,等待时间分摊到多个请求中。在大多数情况下,这会导致更高的流吞吐量。
注意:在某些情况下,通过将其扩展到非常高的并行度来提高吞吐量MapFunction也是可能的,但通常会带来非常高的资源成本:拥有更多并行 MapFunction 实例意味着更多任务、线程、Flink 内部网络连接、网络与数据库、缓冲区和一般内部簿记开销的连接。
先决条件
如上一节所示,对数据库(或键/值存储)实现适当的异步 I/O 需要该数据库的客户端支持异步请求。许多流行的数据库都提供这样的客户端。
在没有这样的客户端的情况下,可以通过创建多个客户端并使用线程池处理同步调用来尝试将同步客户端变为有限的并发客户端。但是,这种方法通常不如适当的异步客户端有效。
异步 I/O API
Flink 的 Async I/O API 允许用户使用带有数据流的异步请求客户端。API 处理与数据流的集成,以及处理顺序、事件时间、容错等。
假设一个目标数据库有一个异步客户端,需要三个部分来实现对数据库的异步 I/O 流转换:
AsyncFunction调度请求的实现
一个回调,它获取操作的结果并将其传递给ResultFuture
在 DataStream 上应用异步 I/O 操作作为转换
以下代码示例说明了基本模式:
/**
* An implementation of the 'AsyncFunction' that sends requests and sets the callback.
*/
class AsyncDatabaseRequest extends AsyncFunction[String, (String, String)