我有一个用例,其中我们正在流事件,对于每个事件,我都必须进行一些查找。查找位于Redis中,我想知道什么是创建连接的最佳方法。火花流将运行40个执行程序,我有5个此类流作业均连接到同一Redis群集。所以我很困惑应该使用哪种方法来创建Redis连接
在驱动程序上创建一个连接对象,并将其广播给执行者(不确定是否真的有效,因为我必须使该对象可序列化)。我可以使用广播变量吗?
为每个分区创建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中的每个分区,我都将创建一个新的连接。
有没有办法为每个分区维护一个连接并缓存该对象,这样我就不必一次又一次地创建连接了?
如果需要,我可以添加更多上下文/信息。
答案 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