我想在spark中执行数据的geoip查找。为此,我使用MaxMind的geoIP数据库。
我想要做的是在每个分区上初始化一次geoip数据库对象,然后使用它来查找与IP地址相关的城市。
spark是否有每个节点的初始化阶段,或者我应该检查实例变量是否未定义,如果是,请在继续之前初始化它?例如。类似的东西(这是python,但我想要一个scala解决方案):
class IPLookup(object):
database = None
def getCity(self, ip):
if not database:
self.database = self.initialise(geoipPath)
...
当然,这样做需要spark会将整个对象序列化,这是文档提醒的。
答案 0 :(得分:6)
在Spark中,每个分区操作可以使用:
def mapPartitions[U](f: (Iterator[T]) ⇒ Iterator[U], preservesPartitioning: Boolean = false)
此映射器将在每个分区上通过元素迭代器执行一次函数f
。我们的想法是,设置资源(如数据库连接)的成本将通过迭代器中许多元素的使用来抵消。
示例:
val logsRDD = ???
logsRDD.mapPartitions{iter =>
val geoIp = new GeoIPLookupDB(...)
// this is local map over the iterator - do not confuse with rdd.map
iter.map(elem => (geoIp.resolve(elem.ip),elem))
}
答案 1 :(得分:2)
这似乎是广播变量的良好用法。您是否查看了该功能的文档?如果您这样做,它无法满足您的要求?
答案 2 :(得分:0)
正如@bearrito所提到的 - 你可以使用加载你的GeoDB然后从你的驱动程序广播它。 另一个需要考虑的选择是提供可用于执行查找的外部服务。它可以是内存缓存,例如Redis / Memcached / Tacheyon或常规数据存储。