Flink 系列第12篇:Flink 维表关联详解

Flink:异步IO关联HBase维表数据 一、使用异步IO关联HBase维表数据优点 为避免在流计算环境中频繁的以同步方式查询外部维表,Flink官方提供使用异步IO与外部系统并发的交互方式,这样可以减轻因为网络交互引起的系统吞吐和延迟问题。当然,为了避免频繁与外部系统进行交互,建议使用内部缓存的方式存储近期容易使用到的维度数据,也就是LRU(最近最少使用)思想,业界经常使用的一个缓存机制是Guava 库提供的 CacheBuilder。 整体的设计思想就是:先用异步IO将HBase维表数据加载到缓存中,这样在关联维表时候先去缓存中查找,如果找不到 阅读详情

一、需求场景

Flink 流式计算中,常需以原始数据流为基础,关联外部维表补充属性,满足业务分析需求。

示例:订单数据流中仅包含收货人所在省的 ID,需关联外部维表(存储省 ID 与省名称的映射关系),补充省名称属性,完善订单数据维度。

实际业务中,维表数据通常存储在 MySQL、HBase、Redis 等外部系统,且存在定时更新需求,需根据业务时效性要求选择合适的关联方案。

常用维表关联方案主要分为以下4类,基本覆盖所有业务场景:

  • 实时查询维表

  • 预加载全量数据

  • LRU 缓存

  • 其他衍生方案

二、实时查询维表

2.1 核心原理

实时查询维表是指在 Flink 算子中直接访问外部数据库(如 MySQL),采用同步调用方式,确保获取的维表数据是最新的。核心逻辑是在 Flink 算子(如 Map 算子)中建立外部系统连接,每条数据流触发一次外部查询,完成关联。

2.2 优缺点

  • 优点:数据实时性最高,确保关联的维表数据是最新状态;

  • 缺点:

    • 高并发场景下,会对外部系统造成巨大访问压力,QPS 需求极高(峰值可达十万到几十万),作业瓶颈转移至外部系统;

    • 同步调用易导致线程阻塞、Task 等待数据返回,影响整体任务吞吐量;

    • 外部系统异常(如连接失败、线程池满)会直接影响 Flink 任务稳定性。

2.3 代码实现(订单关联城市名称)

以订单数据为例,根据下单用户的城市 ID,关联 MySQL 维表获取城市名称,核心代码如下:

2.3.1 订单实体类

public class Order {
    private Integer cityId;
    private String userName;
    private String items;
    private String cityName; // 关联维表后补充的属性

    // 无参构造
    public Order() {}

    // 带参构造(关联后使用)
    public Order(Integer cityId, String userName, String items, String cityName) {
        this.cityId = cityId;
        this.userName = userName;
        this.items = items;
        this.cityName = cityName;
    }

    // getter/setter 方法
    public Integer getCityId() {
        return cityId;
    }

    public void setCityId(Integer cityId) {
        this.cityId = cityId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getItems() {
        return items;
    }

    public void setItems(String items) {
        this.items = items;
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    @Override
    public String toString() {
        return "Order{" +
                "cityId=" + cityId +
                ", userName='" + userName + '\'' +
                ", items='" + items + '\'' +
                ", cityName='" + cityName + '\'' +
                '}';
    }
}

2.3.2 实时查询维表算子

import org.apache.flink.api.common.functions.RichMapFunction;
import org.apache.flink.configuration.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class DimSync extends RichMapFunction<String, Order> {

    private static final Logger LOGGER = LoggerFactory.getLogger(DimSync.class);
    private Connection conn = null; // 外部数据库连接

    /**
     * 初始化方法:Task启动时执行,创建数据库连接
     */
    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        // 建立MySQL连接(需引入MySQL驱动依赖)
        conn = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/dim?characterEncoding=UTF-8",
                "admin",
                "admin"
        );
    }

    /**
     * 核心处理方法:每条数据触发一次维表查询
     */
    @Override
    public Order map(String in) throws Exception {
        // 解析输入的JSON格式订单数据
        JSONObject jsonObject = JSONObject.parseObject(in);
        Integer cityId = jsonObject.getInteger("city_id");
        String userName = jsonObject.getString("user_name");
        String items = jsonObject.getString("items");

        // 根据city_id查询MySQL维表,获取city_name
        PreparedStatement pst = conn.prepareStatement("select city_name from info where city_id = ?");
        pst.setInt(1, cityId);
        ResultSet resultSet = pst.executeQuery();
        String cityName = null;
        while (resultSet.next()){
            cityName = resultSet.getString(1);
        }
        pst.close(); // 关闭PreparedStatement,避免资源泄露

        // 返回关联后的订单数据
        return new Order(cityId, userName, items, cityName);
    }

    /**
     * 关闭方法:Task结束时执行,释放数据库连接
     */
    @Override
    public void close() throws Exception {
        super.close();
        if (conn != null && !conn.isClosed()) {
            conn.close(); // 释放连接,避免打满MySQL连接数
        }
    }
}

2.4 注意事项

  • 适用场景:仅适用于小数据量维表查询,避免高并发场景下压垮外部系统;

  • 连接管理:需妥善处理外部系统连接,建议使用线程池管理连接,避免单条数据创建一个连接;

  • 资源释放:必须在 close\(\) 方法中释放数据库连接、PreparedStatement 等资源,防止连接泄露导致外部系统连接数耗尽,进而引发任务失败。

三、预加载全量数据

3.1 核心原理

为解决实时查询维表带来的外部系统频繁访问、连接压力大的问题,预加载全量数据采用“一次性加载+定时更新”的思路:

  • Flink 任务启动时,将外部维表的全量数据加载到内存中;

  • 数据流处理时,直接在内存中进行关联,无需访问外部数据库;

  • 通过定时任务拉取维表最新数据,更新内存中的缓存,解决维表数据更新无法感知的问题。

3.2 优缺点

  • 优点:仅需一次性访问外部系统,大幅降低外部系统压力,关联效率极高(内存查询);

  • 缺点:

    • 内存消耗大:全量维表数据缓存于内存,不适用于数据量较大的维表;

    • 数据延迟:定时更新机制导致维表数据存在延迟,无法实时获取最新数据;

    • 维表更新感知不及时:若维表数据更新频繁,定时更新间隔难以平衡延迟与性能。

3.3 代码实现(定时拉取城市维表)

import org.apache.flink.api.common.functions.RichMapFunction;
import org.apache.flink.configuration.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class WholeLoad extends RichMapFunction<String, Order> {

    private static final Logger LOGGER = LoggerFactory.getLogger(WholeLoad.class);
    private ScheduledExecutorService executor; // 定时任务线程池
    private Map<String, String> cache; // 内存缓存,存储city_id与city_name的映射

    /**
     * 初始化方法:启动定时任务,定时拉取维表数据
     */
    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        // 初始化缓存(可使用HashMap、ConcurrentHashMap等线程安全集合)
        cache = new ConcurrentHashMap<>();
        // 初始化定时任务线程池,每隔5分钟拉取一次维表数据
        executor = Executors.newSingleThreadScheduledExecutor();
        executor.scheduleAtFixedRate(
                this::load, // 定时执行的方法(拉取维表数据)
                5, // 延迟5秒后开始第一次执行
                5, // 每次执行间隔5分钟
                TimeUnit.MINUTES
        );
        // 首次启动时主动拉取一次数据
        load();
    }

    /**
     * 核心处理方法:从内存缓存中查询维表数据,完成关联
     */
    @Override
    public Order map(String value) throws Exception {
        JSONObject jsonObject = JSONObject.parseObject(value);
        Integer cityId = jsonObject.getInteger("city_id");
        String userName = jsonObject.getString("user_name");
        String items = jsonObject.getString("items");
        // 从内存缓存中获取city_name(无需访问外部数据库)
        String cityName = cache.get(String.valueOf(cityId));
        return new Order(cityId, userName, items, cityName);
    }

    /**
     * 维表数据拉取方法:从MySQL拉取全量维表数据,更新内存缓存
     */
    public void load() throws Exception {
        Class.forName("com.mysql.jdbc.Driver"); // 加载MySQL驱动
        Connection con = DriverManager.getConnection(
                "jdbc:mysql://localhost:3306/dim?characterEncoding=UTF-8",
                "admin",
                "admin"
        );
        PreparedStatement statement = con.prepareStatement("select city_id,city_name from info");
        ResultSet rs = statement.executeQuery();
        // 清空原有缓存,更新为最新数据(避免数据冗余)
        cache.clear();
        while (rs.next()) {
            String cityId = rs.getString("city_id");
            String cityName = rs.getString("city_name");
            cache.put(cityId, cityName);
        }
        // 释放资源
        rs.close();
        statement.close();
        con.close();
        LOGGER.info("维表数据拉取完成,缓存大小:{}", cache.size());
    }

    /**
     * 关闭方法:停止定时任务,释放资源
     */
    @Override
    public void close() throws Exception {
        super.close();
        if (executor != null && !executor.isShutdown()) {
            executor.shutdown(); // 停止定时任务线程池
        }
    }
}

3.4 注意事项

  • 适用场景:维表数据量小、实时性要求不高,且数据更新频率较低的场景;

  • 缓存选择:需使用线程安全的集合(如 ConcurrentHashMap),避免多线程操作缓存出现数据异常;

  • 定时间隔:根据维表更新频率设置合理的定时拉取间隔,平衡数据延迟与系统性能;

  • 资源释放:停止任务时需关闭定时任务线程池,避免线程泄露。

四、LRU 缓存

4.1 核心原理

LRU(Least Recently Used,最近最少使用)是一种缓存淘汰算法,核心逻辑是:当缓存容量达到上限时,淘汰最近最少使用的冷数据,保留查询频率高的热数据。

Flink 中使用 LRU 缓存关联维表的思路:

  • 利用 Flink 的 RichAsyncFunction(异步 IO)读取外部维表(如 HBase)数据到 LRU 缓存;

  • 关联时优先查询缓存,缓存命中则直接返回结果;

  • 缓存未命中时,通过异步客户端查询外部维表,将结果插入缓存后返回,同时触发 LRU 淘汰机制(若缓存满)。

补充:异步 IO(RichAsyncFunction)的核心作用是解决与外部系统交互时,网络延迟成为系统瓶颈的问题,通过并发异步请求,避免同步等待导致的线程阻塞,提升任务吞吐量。

4.2 优缺点

  • 优点:

    • 缓存热数据,减少外部系统访问次数,降低网络延迟和外部系统压力;

    • 异步 IO 支持并发请求,提升任务吞吐量;

    • 缓存容量可控,通过淘汰冷数据,降低内存消耗。

  • 缺点:

    • 数据存在延迟:缓存数据有过期时间,维表数据更新后无法实时同步;

    • 实现复杂度高于前两种方案,需配置缓存参数、异步客户端。

4.3 依赖与代码实现

4.3.1 依赖引入(HBase 异步客户端)

<!-- HBase 异步客户端依赖 -->
<dependency>
    <groupId>org.hbase</groupId>
    <artifactId>asynchbase</artifactId>
    <version>1.8.2</version>
</dependency>
<!-- Guava 缓存依赖(用于实现LRU缓存) -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.1-jre</version>
</dependency>

4.3.2 LRU 缓存与异步关联代码

import org.apache.flink.api.common.functions.RichAsyncFunction;
import org.apache.flink.configuration.Configuration;
import org.apache.flink.util.Collector;
import org.hbase.async.GetRequest;
import org.hbase.async.HBaseClient;
import org.hbase.async.KeyValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSONObject;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeUnit;

public class LRU extends RichAsyncFunction<String, Order> {

    private static final Logger LOGGER = LoggerFactory.getLogger(LRU.class);
    private static final String HBASE_TABLE = "info"; // HBase维表名称
    private Cache<String, String> lruCache; // LRU缓存
    private HBaseClient hbaseClient; // HBase异步客户端

    /**
     * 初始化方法:创建HBase客户端和LRU缓存
     */
    @Override
    public void open(Configuration parameters) throws Exception {
        super.open(parameters);
        // 1. 初始化HBase异步客户端(指定HBase地址和端口)
        hbaseClient = new HBaseClient("127.0.0.1", "7071");

        // 2. 初始化LRU缓存
        lruCache = CacheBuilder.newBuilder()
                .maximumSize(10000) // 缓存最大容量(10000条)
                .expireAfterWrite(60, TimeUnit.SECONDS) // 缓存过期时间(1分钟)
                .build(); // 默认使用LRU淘汰算法
    }

    /**
     * 异步处理方法:异步查询缓存/维表,完成关联
     */
    @Override
    public void asyncInvoke(String input, Collector<Order> resultFuture) throws Exception {
        // 解析输入的JSON格式订单数据
        JSONObject jsonObject = JSONObject.parseObject(input);
        Integer cityId = jsonObject.getInteger("city_id");
        String userName = jsonObject.getString("user_name");
        String items = jsonObject.getString("items");
        String cityIdStr = String.valueOf(cityId);

        // 1. 先查询LRU缓存
        String cacheCityName = lruCache.getIfPresent(cityIdStr);
        if (cacheCityName != null) {
            // 缓存命中,直接返回关联结果
            Order order = new Order();
            order.setCityId(cityId);
            order.setItems(items);
            order.setUserName(userName);
            order.setCityName(cacheCityName);
            resultFuture.collect(order);
            return;
        }

        // 2. 缓存未命中,异步查询HBase维表
        hbaseClient.get(new GetRequest(HBASE_TABLE, cityIdStr))
                .addCallback((List<KeyValue> arg) -> {
                    // 回调函数:HBase查询完成后执行
                    for (KeyValue kv : arg) {
                        String cityName = new String(kv.value());
                        // 构建关联后的订单数据
                        Order order = new Order();
                        order.setCityId(cityId);
                        order.setItems(items);
                        order.setUserName(userName);
                        order.setCityName(cityName);
                        // 发送结果
                        resultFuture.collect(order);
                        // 将查询结果存入LRU缓存,供后续使用
                        lruCache.put(cityIdStr, cityName);
                    }
                    return null;
                });
    }

    /**
     * 关闭方法:释放客户端和缓存资源
     */
    @Override
    public void close() throws Exception {
        super.close();
        if (hbaseClient != null) {
            hbaseClient.shutdown(); // 关闭HBase异步客户端
        }
        if (lruCache != null) {
            lruCache.invalidateAll(); // 清空缓存
        }
    }
}

4.4 注意事项

  • 异步 IO 使用:必须搭配异步客户端(如 HBase 异步客户端),若无异步客户端,可自行创建线程池模拟异步请求,避免同步等待;

  • 缓存配置:根据业务场景合理设置缓存容量和过期时间,平衡内存消耗与数据延迟;

  • 异常处理:需添加回调异常处理逻辑,避免 HBase 查询失败导致任务阻塞;

  • 适用场景:维表数据量大、存在明显冷热数据区分,且实时性要求中等的场景。

五、其他衍生方案

除上述三种核心方案外,可根据业务需求衍生出多种维表关联方式,主要包括:

  • 维表广播:将维表数据封装为广播流,与原始数据流进行广播连接,适用于维表数据量小、更新频率低的场景,可避免重复查询;

  • 自定义异步线程池:通过创建自定义线程池,模拟异步请求,解决无异步客户端的外部系统关联问题;

  • Flink SQL 扩展:扩展 Flink SQL 的维表关联功能,直接使用 SQL Join 语法关联外部维表(如 MySQL、HBase),简化开发流程,适用于 SQL 化开发场景。

六、方案选型建议

维表关联方案的选型需结合业务场景,核心关注三个维度:维表数据量、实时性要求、外部系统性能,具体建议如下:

  • 实时性要求极高、维表数据量小 → 实时查询维表;

  • 实时性要求低、维表数据量小 → 预加载全量数据;

  • 实时性要求中等、维表数据量大、存在冷热数据 → LRU 缓存(搭配异步 IO);

  • SQL 化开发、维表数据量适中 → Flink SQL 扩展维表关联;

  • 维表数据量小、更新频率低 → 维表广播。

总体而言,各类方案可相互结合衍生新的解决方案,核心是从业务本身出发,平衡数据实时性、系统性能和开发复杂度。

Flink预加载分区维表,实时更新维表配置信息 总体来讲,关联维表有三个基础的方式:实时数据库查找关联(Per-Record Reference Data Lookup)、预加载维表关联(Pre-Loading of Reference Data)和维表变更日志关联(Reference Data Change Stream),而根据实现上的优化可以衍生出多种关联方式,且这些优化还可以灵活组合产生不同效果(不过为了简单性这里不讨论同时应用多种优化的实现方式)。1:job初始化时 每个分区open 只加载自己那部分的配置, 不用每个分区都全量加载。 阅读详情

相关推荐

FlinkSQL MySQL维表关联

需求:消费Kafka数据,进行数据清洗及维表关联补齐字段,最后结果写入Kafka。 import java.time.Duration import com.sm.function.udf._ import com.sm.common.conf.PropManager import com.sm.constants.Constants import com.sm.utils.FlinkUtils import org.apache.flink.api.common.restartstrategy..

L, there! 2629

Flink 实时维度表join达到实时配置更新的几种方式总结

1、ETL背景 在我们日常工作中,经常会有一些实时的需求,这些需求往往都是一些拉宽的需求,为了给实时数仓来进行OLAP对来进行Ad-hoc查询,但是我们工作中一些维度表的数据是会发生变化的,可能是缓慢变化维度,那么这个时候就需要进行flink连接其他数据源来进行查询,那么这个时候我们肯定可以想到就是来一条查一次,这个是肯定可以做到的,但是在大数据场景下,我们是不是会觉得有点慢呢,我们是否有更好的解决方案,就像我写代码的时候 有时候就会思考有没有更好的解决方案,但是针对于要进行交付给用户,所以我们并没有那么多

百看不如一RUN 3773

空0006

6。

Direction_Wind的博客 1747

Flink(三十五)—— Flink 使用 broadcast 实现维表或配置的实时更新

一、案例分析 维表服务在 Flink 中是一个经常遇到的业务场景,例如: 客户端上报的用户行为日志只包含了城市 Id,可是下游处理数据需要城市名字 商品的交易日志中只有商品 Id,下游分析数据需要用到商品所属的类目 物联网温度报警的场景中,处理的是设备上报的一条条温度信息,之前的报警规则是:只要温度大于 20 度需要报警,现在需要改成大于 18 度则报警。这里的报警阈值需要动态调整,因此不建议将代码写死 对于上述的场景,实际上都可以通过维表服务的方式来解决。 二、 维表方案

weixin_42073629的博客 2464

“风色幻想XX:交错轨迹游戏卡顿:从解决d3dx9_xx.dll缺失开始——风色幻想XX优化指南

《风色幻想XX:交错轨迹》作为一款深受玩家喜爱的角色扮演游戏,以其丰富的剧情、独特的角色设定和精美的画面赢得了广泛的赞誉。然而,在游戏过程中,部分玩家可能会遇到游戏卡顿的问题,这不仅影响了游戏体验,还可能让玩家错失精彩的剧情和战斗瞬间。在众多导致游戏卡顿的因素中,d3dx9_xx.dll文件的缺失往往是一个不容忽视的原因。

czl922的博客 1255

STM32CubeMX HAL实战:JY901S串口数据解析与姿态解算

本文详细介绍了如何使用STM32CubeMX HAL库实现JY901S六轴姿态传感器的串口数据解析与姿态解算。从基础硬件连接到USART3配置,再到数据接收状态机实现和传感器校准方法,最后深入讲解互补滤波与Mahony滤波算法在姿态解算中的应用。通过实战代码演示,帮助开发者快速掌握无人机、机器人等项目中关键姿态数据处理技术。

weixin_28703489的博客 429

七、Flink维度流实时更新与事实流Connect

两条流按 key 进行 Connect,维度流实时更新与事实流进行匹配。

猫猫爱吃小鱼粮 1082

APS生产排程系统——ERP、MES、APS系统的关联和区别

APS生产排程系统——ERP、MES、APS系统的关联和区别

这里有一只小马吖 2万+

实时数仓之Flink维表关联难点解决方案

1、维表关联的典型场景和考量标准 1.1、维表关联的典型场景 在实时数仓中,我们经常需要做维表关联,但是用户维表一般在业务数据库中,业务方是不允许大数据部门直接到业务数据库进行维表关联,因为这会影响线上业务。此时我们需要将用户维表采集到大数据平台,然后事实表就可以直接跟维表进行关联,从而生成事实宽表,具体场景如下图所示。 在生产环境中,我们通过数据采集平台将用户维表采集到大数据平台,然后事实表跟用户维表直接关联就可以了吗? 答案,是不行的。因为在生产环境中,我们还需要考虑如下问题: (1)高流量的情况下

雾岛与鲸的博客 1万+

ESP32开发环境与微信小程序通信的完整示例

通过搭建稳定的esp32开发环境,实现其与微信小程序间的双向通信,涵盖Wi-Fi连接、数据收发与协议设计,为物联网应用提供低成本解决方案。

weixin_42126677的博客 1130

GD32 TIMER0 PWM输出死活没波形?别忘了这个关键配置(附完整代码)

本文详细解析了GD32 TIMER0 PWM输出无波形的常见问题,特别强调了高级定时器特有的主输出使能配置。通过完整的代码示例和调试技巧,帮助开发者快速解决PWM输出问题,适用于无刷电机控制等嵌入式应用场景。

weixin_30906185的博客 397

【Flink系列】开发篇:1. Flink维表关联方案

谈一谈个人对Flink中不同维表关联方案的理解和尝试后发现的一些问题

m0_37935211的博客 2921

STM32+ESP8266+MQTT协议连接阿里云物联网平台

一、环境介绍 单片机采用:STM32F103C8T6 上网方式:采用ESP8266,也可以使用其他设备代替,只要支持TCP协议即可。比如:GSM模块、有线网卡等。 开发软件:keil5 二、实现功能 通过阿里云物联网服务器实现设备数据远程上传、下发,实现数据交互。 在当前使用的开发板上有4盏LED灯、一个蜂鸣器、4个按键。 三、阿里云物联网服务器创建步骤 说明:如果没有账号的话,先点击网页右上角,注册一个账号,并完成实名认证再继续下一步。 产品名称根据自己情况填...

6万+

Flink 维表关联方案

Flink 维表关联方案

猫猫爱吃小鱼粮 3492

华为OD机考双机位C卷 - 文件存储系统的排序(Java & Python & JS & GO & C++ & C)

华为OD机考双机位C卷 - 文件存储系统的排序, 提供Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。

算法大师! 777

[Unity开发] [PICO]避坑指南:PICO商店上传APP时PXR Platform APPID设定详解

PICO开发者上传Unity应用时常见的"APPID不符"问题,主要源于混淆了开发者后台两个不同位置的APPID。

每日出拳老爷子的博客 554

Flink 维表关联多种方案对比

提到 Flink SQL 如何 Join 两个数据流,有读者反馈说如果不打算用 SQL 或者想自己实现底层操作,那么如何基于 DataStream API 来关联维表呢?实际上由于 Flink DataStream API 的灵活性,实现这个需求的方式是非常多样的,但是大部分用户很难在设计架构时就考虑得很全面,可能会走不少弯路。 针对于此,笔者根据工作经验以及社区资源整理了用 DataStream 实现 Join 维表的常见方式,并给每种的方式优劣和适用场景给出一点可作为参考的个人观点。 衡量指标 总

weixin_42073629的博客 3503

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

【flink番外篇】15、Flink维表实战之6种实现方式-通过Temporal table实现维表数据join

一、Flink 专栏Flink 专栏系统介绍某一知识点,并辅以具体的示例进行说明。1、Flink 部署系列 本部分介绍Flink的部署、配置相关基础内容。2、Flink基础系列 本部分介绍Flink 的基础部分,比如术语、架构、编程模型、编程指南、基本的datastream api用法、四大基石等内容。3、Flik Table API和SQL基础系列 本部分介绍Flink Table Api和SQL的基本用法,比如Table API和SQL创建库、表用法、查询、窗口函数、catalog等等内容。4、Flik

alanchanchn的专栏 7万+

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

flink维表关联系列之Redis维表关联:实时查询

点击上方蓝字关注~ 在做维表关联如果要求低延时,即维表数据的变更能够被立刻感知到,所以就要求在查询时没有缓存策略,直接查询数据库维表信息。本篇以实时查询redis为例,要求r...

张普的专栏 3342

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Flink维表Join实践

这个文章是根据 【实时数仓篇】基于 Flink 的典型 ETL 场景实现 写的,对视频中讲解的四种维表Join分别实现了一些Demo。 常见的维表Join方式有四种: 预加载维表 热存储维表 广播维表 Temporal table function join 下面分别使用这四种方式来实现一个join的需求,这个需求是:一个主流中数据是用户信息,字段包括用户姓名、城市id;维表是城市数据,字段包括城市ID、城市名称。要求用户表与城市表关联,输出为:用户名称、城市ID、城市名称。 1、 预加载维表 通过定义

鸣宇淳的专栏 5285

Flink DataStream 关联维表实战

上篇博客提到 Flink SQL 如何 Join 两个数据流,有读者反馈说如果不打算用 SQL 或者想自己实现底层操作,那么如何基于 DataStream API 来关联维表呢?实际上由...

Ververica的博客 2829

flink维表关联系列之Hbase维表关联:LRU策略

维表关联系列目录:一、维表服务与Flink异步IO二、Mysql维表关联:全量加载 三、Hbase维表关联:LRU策略 四、Redis维表关联:实时查询 五、kafka维表关联:广播方式 六、自定义异步查询 LRU LRU(Least Recently Used),最近最少使用缓存淘汰算法,认为最近访问过的数据在将来被访问的概率也比较大,当内存达到上限去淘汰那些最近访问较少的数据。 在Flink中做维表关联时,如果维表的数据比较大,无法一次性全部加载到内存中,而在业务上也允许一定数据的延时,那么就可以

u013939918的博客 1891

flink维表关联系列之Mysql维表关联:全量加载

在维表关联中定时全量加载是针对维表数据量较少并且业务对维表数据变化的敏感程度较低的情况下可采取的一种策略,对于这种方案使用有几点需要注意: 全量加载有可能会比较耗时,所以必须是一个异步加载过程 内存维表数据需要被流表数据关联读取、也需要被定时重新加载,这两个过程是不同线程执行,为了尽可能保证数据一致性,可使用原子引用变量包装内存维表数据对象,即AtomicReference 查内存维表数据非异步io过程 具体实例:广告流量统计,广告流量数据包含:广告位id,用户设备id,事件类型(点击、浏览),发生时间

雾岛与鲸的博客 2222

flink 维表关联多种方式

1.实时查询维表 优点:维表数据实时更新,可以做到实时同步到。 缺点:访问压力大,如果失败会造成线程阻塞。 实时查询维表是指用户在Flink算子中直接访问外部数据库。这种方式可以保证数据是最新的,但是当我们流计算数据过大,会对外部系统带来巨大的访问压力,比如:连接失败,连接池满等情况,就会导致线程阻塞。task等待数据返回. 核心就是通过Map算子中建立访问外部系统的连接。核心代码如下: public static void main(String[] args) throws Exce.

weixin_40954192的博客 4423

详解flink中Look up维表的使用

在流式计算中,维表是一个很常见的概念,一般用于sql的join中,对流式数据进行数据补全,比如我们的source stream是来自日志的订单数据,但是日志中我们只是记录了订单商品的id,并没有其他的信息,但是我们把数据存入数仓进行数据分析的时候,却需要商品名称、价格等等其他的信息,这种问题我们可以在进行流处理的时候通过查询维表的方式对数据进行数据补全。 维表一般存储在外部存储中,比如mysql、hbase、redis等等,今天我们以mysql为例,讲讲flink中维表的使用。

公众号[大数据技术与应用实战],分享大数据实战案例 4308
上一篇: Flink 系列第11篇:Flink 重分区算子详解
下一篇: Flink 系列第13篇:Flink 生产环境中的并行度与资源配置
juniperhan
博客等级 码龄1年 132粉丝 44原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值