《高级》Flink异步io链接Redis--Java和Scala版

最近发现好多小伙伴不知道如何异步链接redis

我准备了两个版本 java版本和scala版本

直接上代码,大部分同学看了应该会懂

刚开始学习flink的同学中间细节的东西,不明白的可以微信联系我,可以进入我的flink微信交流群。

 

喜欢flink的朋友,支持一下原创,可以关注我的公众号:

 

先看java版本

import com.alibaba.fastjson.JSON;import org.apache.flink.api.common.serialization.SimpleStringSchema;import org.apache.flink.configuration.Configuration;import org.apache.flink.streaming.api.datastream.AsyncDataStream;import org.apache.flink.streaming.api.datastream.DataStream;import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;import org.apache.flink.streaming.api.functions.async.ResultFuture;import org.apache.flink.streaming.api.functions.async.RichAsyncFunction;import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer08;import redis.clients.jedis.Jedis;import redis.clients.jedis.JedisPool;import redis.clients.jedis.JedisPoolConfig;import java.util.Collections;import java.util.Properties;import java.util.concurrent.CompletableFuture;import java.util.concurrent.TimeUnit;import java.util.function.Supplier;
public class AsynFlinkRedisJava {    public static void main(String args[]) throws Exception{        final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();        env.enableCheckpointing(500);        Properties props = new Properties();        props.setProperty("bootstrap.servers", "localhost:9092");        props.setProperty("zookeeper.connect", "localhost:2181");        props.setProperty("group.id", "flink-kafka");        FlinkKafkaConsumer08 consumer = new FlinkKafkaConsumer08("flink1", new SimpleStringSchema(), props);        DataStream<String> stream = env.addSource(consumer);        DataStream<String> resultStream = AsyncDataStream.unorderedWait(stream, new AsyncRedis(),1000, TimeUnit.MICROSECONDS, 100);        resultStream.print();        env.execute("kaishi");    }}class AsyncRedis extends RichAsyncFunction<String, String> {    private transient JedisPool pool;    @Override    public void open(Configuration parameters) throws Exception {        super.open(parameters);        pool= new JedisPool(new JedisPoolConfig(), "localhost", 6379);    }    @Override    public void asyncInvoke(String input, final ResultFuture<String> resultFuture) throws Exception {        CompletableFuture.supplyAsync(new Supplier<String>() {            @Override            public String get() {                try {                    String imei = JSON.parseObject(input).get("imei").toString();                    Jedis jedis = pool.getResource();                    String result = jedis.hget("DC_IMEI_APPID",imei);                    pool.returnResource(jedis);                    return result;                } catch (Exception e) {                    System.out.println(e);                    return null;                }            }        }).thenAccept( (String dbResult) -> {            resultFuture.complete(Collections.singleton(dbResult));        });    }}

再看scala版本:

import java.util.Propertiesimport org.apache.flink.api.common.serialization.SimpleStringSchemaimport org.apache.flink.streaming.api.scala.{AsyncDataStream, DataStream, StreamExecutionEnvironment, _}import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer08import com.alibaba.fastjson.JSONimport redis.clients.jedis.{Jedis, JedisPool, JedisPoolConfig}import java.util.concurrent.TimeUnitimport org.apache.flink.streaming.api.scala.async.{AsyncFunction, ResultFuture}import scala.concurrent.{ExecutionContext, Future}object AsynFlinkRedis {  def main(args: Array[String]): Unit = {    val env = StreamExecutionEnvironment.getExecutionEnvironment    val properties = new Properties()    //kafka位置 老版本的 kafka是配置zookeeper地址    properties.setProperty("bootstrap.servers","localhost:9092")    properties.setProperty("zookeeper.connect","localhost:2181")    val topic = "flink1"    properties.setProperty("group.id", "test-flink")    val kafkStream = new FlinkKafkaConsumer08(topic,new SimpleStringSchema(),properties)    val stream = env.addSource(kafkStream)    stream.print()    val resultStream=AsyncDataStream.unorderedWait(stream,new RedisAsyncFunction(), 1000, TimeUnit.MILLISECONDS, 100)    resultStream.print()    env.execute()  }}class RedisAsyncFunction extends  AsyncFunction[String,String]{   lazy  val pool = new JedisPool(new JedisPoolConfig,"localhost",6379)  override def asyncInvoke(input: String, resultFuture: ResultFuture[String]): Unit = {    Future {      //获取kafka日志的imei号      val imei = JSON.parseObject(input).get("imei").toString      //从redis中获取imei对应的userid      println(pool.getNumActive)      val jedis = pool.getResource      val useridJson =jedis.hget("DC_IMEI_APPID",imei)      print(useridJson)      resultFuture.complete(Seq(useridJson))      pool.returnResource(jedis)    }(ExecutionContext.global)}}

kafka练习日志:

{"accStatus":"NULL","addr":"","alertType":"stayAlert","fenceId":"NULL","gpsTime":"2019-01-29 23:45:01","iccid":"NULL","imei":"868620190220000","imsi":"NULL","lat":"46.795862","lng":"134.011538","offlineTime":"NULL","postTime":"2019-01-30 00:00:00","time":"NULL","type":"DEVICE"}

redis测试数据:

hset DC_IMEI_APPID 868620190220000 "{\"allFullId\":\"1,130396,130395,129659\",\"appId\":\"TRACKER\",\"userId\":\"129659\",\"mcType\":\"GT06N\",\"timeZone\":\"UTCA08:00\"}"
<think>好的,我需要帮助用户了解Flink异步IO的用法及示例。首先,用户提供的引用中有三个来源,我需要结合这些内容来整理回答。 首先,引用[1]提到了Flink异步IO的基本概念一个示例,但要注意用户提供的引用中可能存在错误,比如用户提到的引用[1]是关于快速排序的,但实际给出的链接是关于Flink异步IO的。这可能是个错误,但按照用户提供的引用内容来处理。需要确认是否有混淆,但根据用户的问题,重点在Flink异步IO,所以可能用户在引用部分有误。但根据用户给出的三个引用链接,都是关于Flink异步IO的,所以应该以这三个引用为基础。 接下来,引用[2][3]提供了具体的实现示例,比如Redis异步读取HTTP客户端的使用。需要将这些内容整合起来,说明异步IO的使用步骤、配置参数注意事项。 用户的需求是了解异步IO的使用方法及示例,因此需要分步骤说明,包括添加依赖、实现AsyncFunction、使用AsyncDataStream工具类,以及参数配置。同时,需要给出具体的代码示例,比如访问Redis或HTTP服务。 另外,用户可能遇到的问题如超时处理、顺序模式与乱序模式的区别,以及资源管理,需要根据引用内容进行解答。例如,引用[3]中提到的capacity参数设置线程池配置,需要强调这些参数的重要性。 最后,生成相关问题需要考虑用户可能进一步想了解的内容,比如性能优化、异常处理、与其他技术的整合等。 现在需要组织这些信息,确保结构清晰,符合用户要求的格式,使用中文回答,正确应用LaTeX语法,并添加引用标识。同时,检查是否有遗漏的关键点,比如AsyncFunction的实现细节,ResultFuture的使用,超时处理等,确保覆盖所有用户可能需要的方面。</think>### Flink异步IO使用方法及示例 Flink异步IO用于提升外部数据访问效率,通过异步请求避免阻塞算子处理。以下为关键步骤示例: #### 一、核心步骤 1. **添加依赖** ```xml <dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-connector-async</artifactId> <version>${flink.version}</version> </dependency> ``` 2. **实现AsyncFunction** ```java public class AsyncHttpRequest extends RichAsyncFunction<String, String> { private transient AsyncHttpClient client; @Override public void open(Configuration parameters) { client = new DefaultAsyncHttpClient(); } @Override public void asyncInvoke(String input, ResultFuture<String> resultFuture) { client.prepareGet("https://api.example.com?q=" + input) .execute(new AsyncCompletionHandler<Response>() { @Override public Response onCompleted(Response response) { resultFuture.complete(Collections.singleton(response.getResponseBody())); return response; } }); } } ``` 3. **应用异步算子** ```java AsyncDataStream.unorderedWait( // 或orderedWait inputStream, new AsyncHttpRequest(), 10, // 超时时间(秒) TimeUnit.SECONDS, 100 // 最大并发请求数 ).print(); ``` #### 二、关键配置参数 - **Capacity**:控制同时处理的请求数(默认100)[^3] - **Timeout**:设定单个请求超时阈值 - **AsyncMode**: - `orderedWait`:保持输入顺序 - `unorderedWait`:允许乱序输出[^1] #### 三、典型应用场景 1. **Redis异步查询** ```java // 引用[2]的Redis访问示例 public class RedisAsyncFunction extends RichAsyncFunction<String, User> { private transient RedisClient redisClient; public void asyncInvoke(String userId, ResultFuture<User> resultFuture) { redisClient.get(userId, new RedisCallback<User>() { public void onComplete(User user) { resultFuture.complete(Collections.singleton(user)); } }); } } ``` 2. **HTTP服务调用** ```java // 引用[3]的高德地图API调用 asyncInvoke方法中配置: client.prepareGet("https://restapi.amap.com/v3/geocode/geo?address="+address+"&key=your_key") ``` #### 四、注意事项 1. **客户端选择**:推荐使用连接池管理的客户端(如Netty/AsyncHttpClient) 2. **异常处理**:需实现`ResultFuture`的超时回调 3. **资源释放**:在`close()`方法中释放连接资源[^2] #### 五、性能优化建议 $$ 吞吐量 = \frac{并发请求数}{平均响应时间} $$ 通过公式可知,提升吞吐量需要: 1. 增加capacity参数值 2. 优化外部系统响应速度 3. 使用连接池复用资源[^3]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值