Flink流处理查询外部数据源的解决方法

Flink流处理查询外部数据源的解决方法

流处理中,常涉及到与外部数据源的交互。例如在实时数仓的设计中通常是流式采集用户的浏览、下单等行为,但是用户信息,SKU、SPU等信息因为是维度表不适合通过流的方式读取(流中无法进行随意消费),而是存储在外部数据库例如Hbase、ClieckHouse的实时性能比较高的分布式数据库中。但是与外部数据源的查询常常是流式计算的瓶颈,下面给出了两种优化方案:旁路缓存技术和Flink提供的异步查询方式。

方案1: 加入旁路缓存模式 (cache-aside-pattern)

旁路缓存模式是一种非常常见的按需分配缓存的模式。

如下图,任何请求优先访问缓存,缓存命中,直接获得数据返回请求。如果未命中则查询数据库,同时把结果写入缓存以备后续请求使用
在这里插入图片描述

这种缓存策略有几个注意点

  1. 缓存要设置过期时间,不然冷数据会常驻缓存浪费资源。
  2. 要考虑维度数据是否会发生变化,如果发生变化要主动更新缓存(防止使用了缓存中的旧数据而产生问题)。

缓存的选型

一般两种:堆缓存(应用程序内存)或者独立缓存(redis,memcache)

  • 堆缓存:从性能角度考虑更加高效,但是可管理性差,其他进程无法维护缓存中数据,比较消耗内存。

补充:Flink状态内存也属于这一种,如果缓存大量维度表信息会消耗大量内存,并且状态管理只能在同一并行度同一key下访问

  • 独立缓存:性能较堆缓存弱一点,但是当数据发生变化时,独立缓存服务管理性更强,如果数据量特别大,独立缓存更容易扩展。缺点是会有创建连接、网络IO等消耗。

方案2: 异步查询

在Flink 流处理过程中,经常需要和外部系统进行交互,用维度表补全事实表中的字段。

例如:在电商场景中,需要一个商品的skuid去关联商品的一些属性,例如商品所属行业、商品的生产厂家、生产厂家的一些情况;在物流场景中,知道包裹id,需要去关联包裹的行业属性、发货信息、收货信息等等。

默认情况下,在Flink的MapFunction中,单个并行只能用同步方式去交互: 将请求发送到外部存储,IO阻塞,等待请求返回,然后继续发送下一个请求。这种同步交互的方式往往在网络等待上就耗费了大量时间。为了提高处理效率,可以增加MapFunction的并行度,但增加并行度就意味着更多的资源,并不是一种非常好的解决方式。

Flink 在1.2中引入了Async I/O,在异步模式下,将IO操作异步化,单个并行可以连续发送多个请求,哪个请求先返回就先处理,从而在连续的请求间不需要阻塞式等待,大大提高了流处理效率。Async I/O 是阿里巴巴贡献给社区的一个呼声非常高的特性,解决与外部系统交互时网络延迟成为了系统瓶颈的问题。
在这里插入图片描述

异步查询实际上是把维表的查询操作托管给单独的线程池完成,这样不会因为某一个查询造成阻塞,单个并行可以连续发送多个请求,提高并发效率。这种方式特别针对涉及网络IO的操作,减少因为请求等待带来的消耗。

使用异步API的先决条件

  1. 正确实现数据库(或键/值存储)的异步I/O交互需要支持异步请求的数据库客户端。许多主流数据库都提供了这样的客户端。
  2. 如果没有这样的客户端,可以通过创建多个客户端并使用线程池处理同步调用的方法,将同步客户端转换为有限并发的客户端。这种方法通常比正规的异步客户端效率稍低。

phoenix目前没有提供异步客户端

Flink的异步I/O API

Flink的异步I/O API 允许用户在流处理中使用异步请求客户端。API处理与数据流的集成,同时还能处理好顺序、事件时间和容错等

在具备异步数据库客户端的基础上,实现数据流转换操作与数据库I/O交互需要具备以下三部分:

  1. 实现分发请求的 AsyncFunction
  2. 获取数据库交互结果并发送给 ResultFuture 的回调函数
  3. 将异步 I/O 操作应用于 DataStream 作为 DataStream 的一次转换操作。
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值