Spark连接redis问题 Caused by: java.io.NotSerializableException

**spark连接Redis的时候报错: **

Caused by: java.io.NotSerializableException: io.jimdb.JimdbNewCluster$$Enhanced
Serialization stack:

刚开始还以为是spark连接redis过程中无法序列化的问题,尝试了很多种方法。
也借鉴过这位老哥写的博客:

https://blog.csdn.net/qq_28743951/article/details/86599918

但是好像都没有用!!!
代码如下:

featureData.rdd.foreach{
      s =>
        redisDataCount += 1L
        val jda = s.getAs[String]("did")
        val redisKey = redisKeys + jda
        val redisValue = s.getAs[String]("feature")
        redisCli.set(redisKey, redisValue) //连接redis
        redisCli.expire(redisKey, 4, TimeUnit.HOURS) //设置超时时间
    }

发现问题:
foreachRDD是基于rdd的一个操作,行为表现与我们在计算操作的部分基本是一致的,这也意味着一个很经典的情况:rdd是分布式的运算。它需要在在不同的机器上运行相同的程序。假设我们给这个函数传递的函数里直接创建redis连接的话,会出现一个序列化错误,因为它需要把这个连接对象序列化之后发送给计算程序,这点无法实现。

解决办法:
那这里,发现问题也就比较好解决了,我们把数据拉回到driver上执行就可以了。

featureData.rdd.collect().foreach{
      s =>
        redisDataCount += 1L
        val jda = s.getAs[String]("did")
        val redisKey = redisKeys + jda
        val redisValue = s.getAs[String]("feature")
        redisCli.set(redisKey, redisValue) //连接redis
        redisCli.expire(redisKey, 4, TimeUnit.HOURS) //设置超时时间

但是如果数据量太大的话,放在driver也是不行的,这里我参考了一位大佬的方法:
利用rdd的分布式特性,rdd使用的也是经典的分区计算模型,每个节点计算的部分数据处于分区中,一般来讲,对于这一个分区的数据,我们建立一个连接对象已经是可以接受的了。
代码如下:

featureData.rdd.foreachPartition{
      partitionOfRecords =>
        val redis = new GetClientJimKV(newJimUrl, host)
        val redisCli = redis.getJimClient
        partitionOfRecords.take(10)
        partitionOfRecords.foreach{
          s =>
            val jda = s.getAs[String]("did")
            val redisKey = redisKeys + jda
            val redisValue = s.getAs[String]("feature")
            redisCli.set(redisKey, redisValue)
            redisCli.expire(redisKey, 4, TimeUnit.HOURS)
        }
    }

参考:

https://juejin.cn/post/7031197529500991518

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值