使用foreachPartition将结果写入外部存储

好久没有写了!!!记录一下 :

最近有个小伙伴问我,使用spark处理的数据存入mysql中老是导致mysql链接超时或中断,我看了一下他的代码,想揍人,

其代码如下:

dstream.foreachRDD {rdd =>
  rdd.foreachPartition{ partitionRecords =>
  val connection = createNewConnection
  //将结果存入外部存储系统中
    partitionRecords.foreach(record => connection.send(record))
  }
}

这种方式不可行!!!

最不济可以这样写:

dstream.foreachRDD {rdd =>
  rdd.foreachPartition{ partitionRecords =>
  val connection = createNewConnection
  //将结果存入外部存储系统中
    partitionRecords.foreach(record => connection.send(record))
	connection.close()  //记得要关闭
  }
}

这样可以保证每个partition只需要链接一次外部存储系统,最起码不会造成锁死等问题,提高了性能,但是并不能使不同的partition直接可以重复利用链接,为了重复利用此链接可以使用连接池来解决,使其不同partition之间可以共享链接:

dstream.foreachRDD {rdd =>
  rdd.foreachPartition{ partitionRecords =>
  val connection = ConnectionPool.getConnection  //使用连接池使不同partition之间共享链接
  //将结果存入外部存储系统中
    partitionRecords.foreach(record => connection.send(record))
	//重用连接池
	ConnectionPool.returnConnection(connection)
  }
}

提高了效率,又不会阻塞链接

另有连接池:

public class ConnectionPool {
    private static LinkedList<Connection> connectionQueue;

    static {
        try {
            Class.forName("com.mysql.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public synchronized static Connection getConnection() {
        try {
            if (connectionQueue == null) {
                connectionQueue = new LinkedList<Connection>();
                for (int i = 0; i < 5; i++) {
                    Connection conn = DriverManager.getConnection(
                            "jdbc:mysql://ip地址:3306/所处路径",
                            "username",
                            "password");
                    connectionQueue.push(conn);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return connectionQueue.poll();

    }
	
    public  static void returnConnection(Connection conn){connectionQueue.push(conn);}
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个简单的使用Python语言继承RichSinkFunction将数据写入外部系统的示例代码: ```python from pyflink.common.serialization import SimpleStringEncoder from pyflink.common.serialization import SimpleStringSchema from pyflink.common.typeinfo import Types from pyflink.datastream import StreamExecutionEnvironment from pyflink.datastream.connectors import FlinkKafkaProducer from pyflink.datastream.functions import RichSinkFunction from pyflink.datastream import StreamExecutionEnvironment, CheckpointingMode class MySinkFunction(RichSinkFunction): def open(self, function_context): # 进行一些初始化工作,例如建立连接等等 pass def invoke(self, value, context): # 将数据写入外部系统 pass def close(self): # 进行一些清理工作,例如关闭连接等等 pass # 创建StreamExecutionEnvironment env = StreamExecutionEnvironment.get_execution_environment() env.set_parallelism(1) # 从数据源获取数据流 data_stream = ... # 将数据流写入外部系统,例如Kafka kafka_producer = FlinkKafkaProducer( "localhost:9092", "my-topic", serialization_schema=SimpleStringSchema(), producer_config={ "bootstrap.servers": "localhost:9092", "acks": "all" } ) data_stream.add_sink(kafka_producer) # 执行任务 env.execute("My Flink job") ``` 在这个示例中,我们自定义了一个名为MySinkFunction的类,继承了RichSinkFunction类,并实现了其中的open()、invoke()和close()方法。在open()方法中,我们可以进行一些初始化工作,例如建立连接等等;在invoke()方法中,我们可以将数据写入外部系统;在close()方法中,我们可以进行一些清理工作,例如关闭连接等等。 然后,我们通过FlinkKafkaProducer将数据流写入Kafka中。最后,我们调用env.execute()方法来执行任务。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值