栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

Spark上的Redis:任务不可序列化

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spark上的Redis:任务不可序列化

在Spark中,

RDD
s(如此
map
处)上的函数被序列化并发送给执行程序进行处理。这意味着这些操作中包含的所有元素都应该可序列化。

Redis连接不可序列化,因为它打开了到目标DB的TCP连接,该TCP连接已绑定到创建它的机器。

解决方案是在本地执行上下文中的执行器上创建那些连接。做到这一点的方法很少。我想到的两个是:

  • rdd.mapPartitions
    :可让您一次处理整个分区,从而分摊创建连接的成本)
  • 单例连接管理器:每个执行者创建一次连接

mapPartitions
仅需对程序结构进行少量更改即可轻松实现:

val perhit = perhitFile.mapPartitions{partition =>     val r = new RedisClient("192.168.1.101", 6379) // create the connection in the context of the mapPartition operation    val res = partition.map{ x =>        ...        val refStr = r.hmget(...) // use r to process the local data    }    r.close // take care of resources    res}

可以使用持有对连接的延迟引用的对象对单例连接管理器进行建模(注意:可变引用也将起作用)。

object RedisConnection extends Serializable {   lazy val conn: RedisClient = new RedisClient("192.168.1.101", 6379)}

然后可以使用该对象实例化每个辅助JVM的1个连接,并用作

Serializable
操作闭包中的对象。

val perhit = perhitFile.map{x =>     val param = f(x)    val refStr = RedisConnection.conn.hmget(...) // use RedisConnection to get a connection to the local data    }}

使用单例对象的优点是开销较小,因为连接仅由JVM创建一次(而不是每个RDD分区1个)

还有一些缺点:

  • 连接的清理很棘手(关机挂钩/计时器)
  • 必须确保共享资源的线程安全

(*)代码用于说明目的。未经编译或测试。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/388177.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号