如何在Spark Streaming for Lookups中创建到数据源的连接

时间:2019-03-15 20:36:08

标签: apache-spark redis spark-streaming spark-streaming-kafka

我有一个用例,其中我们正在流事件,对于每个事件,我都必须进行一些查找。查找位于Redis中,我想知道什么是创建连接的最佳方法。火花流将运行40个执行程序,我有5个此类流作业均连接到同一Redis群集。所以我很困惑应该使用哪种方法来创建Redis连接

  1. 在驱动程序上创建一个连接对象,并将其广播给执行者(不确定是否真的有效,因为我必须使该对象可序列化)。我可以使用广播变量吗?

  2. 为每个分区创建Redis连接,但是我以这种方式编写了代码

    val update = umfRecsStream.transform(rdd => { // on driver if (MetaDataRefresh.isNewDay) { ..... } rdd }) update.foreachRDD(rdd => { rdd.foreachPartition(partition => { partition.foreach(kafkaKey_trans => { // perform some lookups logic here } } })

现在,如果我在每个分区内创建一个连接,则意味着对于每个RDD和该RDD中的每个分区,我都将创建一个新的连接。

有没有办法为每个分区维护一个连接并缓存该对象,这样我就不必一次又一次地创建连接了?

如果需要,我可以添加更多上下文/信息。

1 个答案:

答案 0 :(得分:2)

1。在驱动程序上创建一个连接对象,并将其广播给执行者(不知道它是否真的有效,因为我必须使该对象可序列化)。我可以使用广播变量吗?

答案-否。由于与连接相关的机器相关数据,大多数连接对象无法序列化。

2。有没有一种方法可以为每个分区维护一个连接并缓存该对象,这样我就不必一次又一次地创建连接?

答案-是的,创建一个连接池并在分区中使用它。这是风格。您可以像这样https://github.com/RedisLabs/spark-redis/blob/master/src/main/scala/com/redislabs/provider/redis/ConnectionPool.scala

创建连接池

然后使用它

dstream.foreachRDD { rdd =>
  rdd.foreachPartition { partitionOfRecords =>
    // ConnectionPool is a static, lazily initialized pool of connections
    val connection = ConnectionPool.getConnection()
    partitionOfRecords.foreach(record => connection.send(record))
    ConnectionPool.returnConnection(connection)  // return to the pool for future reuse
  }
}

请检查以下内容: design pattern for using foreachRDD