如何在spark中执行初始化?

时间:2014-11-21 17:14:55

标签: scala apache-spark

我想在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会将整个对象序列化,这是文档提醒的。

3 个答案:

答案 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或常规数据存储。