1.$sample stage could not find a non-duplicate document while using a random cursor

  这个问题比较难解决,因为我用mongodb spark connector没用到sample,但是在生成RDD的过程中会进行sample操作,所以没法避免,出现这个问题的原因也不可控,在jira上有这个问题,但并没有一个合理的解决方案,stackoverflow上也没有解决办法,就我个人而言,出现这个问题有几个特征:

  a) 出现在sharding 集群中,因为我单机不用spark,也不会出现这种问题,而在搜索过程中发现遇到这问题的人非常少,而且很多都不可再现,而spark连sharding集群会一直出这个问题。

  b) 似乎和shardsvr有直接联系,出现这问题的机器一直是其中一台shardsvr,而之前同样的程序在集群中是跑通过的,所以怀疑是上次异常断电导致这台shardsvr有什么设置出现了问题。

  解决方案目前可以使用sparkSession.config设置这项参数,也可以直接在readConfig里设置这项参数,如sparkSession进行如下设置:

  1. lazy val spark = SparkSession.builder()
  2. .master("spark://192.168.12.161:7077")
  3. .config(new SparkConf().setJars(Array("hdfs://192.168.12.161:9000/mongolib/mongo-spark-connector_2.11-2.0.0.jar",
  4. "hdfs://192.168.12.161:9000/mongolib/bson-3.4.2.jar",
  5. "hdfs://192.168.12.161:9000/mongolib/mongo-java-driver-3.4.2.jar",
  6. "hdfs://192.168.12.161:9000/mongolib/mongodb-driver-3.4.2.jar",
  7. "hdfs://192.168.12.161:9000/mongolib/mongodb-driver-core-3.4.2.jar",
  8. "hdfs://192.168.12.161:9000/mongolib/commons-io-2.5.jar",
  9. "hdfs://192.168.12.161:9000/mongolib/config-1.2.1.jar",
  10. "hdfs://192.168.12.161:9000/ScheduleImport.jar")))
  11. .config("spark.cores.max", 80)
  12. .config("spark.executor.cores", 16)
  13. .config("spark.executor.memory", "32g")
  14. .config("spark.mongodb.input.uri", s"mongodb://${user}:${passwd}@192.168.12.161:27017/wenshu.origin2?authSource=${authDB}")
  15. .config("spark.mongodb.output.uri", s"mongodb://${user}:${passwd}@192.168.12.160:27017/wenshu.backup?authSource=${authDB}")
  16. .config("spark.mongodb.input.partitionerOptions.samplesPerPartition", 1)
  17. .getOrCreate()

   这个参数在Connector中的作用如下:

  1. override def partitions(connector: MongoConnector, readConfig: ReadConfig, pipeline: Array[BsonDocument]): Array[MongoPartition] = {
  2. Try(PartitionerHelper.collStats(connector, readConfig)) match {
  3. case Success(results) =>
  4. val matchQuery = PartitionerHelper.matchQuery(pipeline)
  5. val partitionerOptions = readConfig.partitionerOptions.map(kv => (kv._1.toLowerCase, kv._2))
  6. val partitionKey = partitionerOptions.getOrElse(partitionKeyProperty, DefaultPartitionKey)
  7. val partitionSizeInBytes = partitionerOptions.getOrElse(partitionSizeMBProperty, DefaultPartitionSizeMB).toInt * 1024 * 1024
  8. val samplesPerPartition = partitionerOptions.getOrElse(samplesPerPartitionProperty, DefaultSamplesPerPartition).toInt
  9.  
  10. val count = if (matchQuery.isEmpty) {
  11. results.getNumber("count").longValue()
  12. } else {
  13. connector.withCollectionDo(readConfig, { coll: MongoCollection[BsonDocument] => coll.count(matchQuery) })
  14. }
  15. val avgObjSizeInBytes = results.get("avgObjSize", new BsonInt64(0)).asNumber().longValue()
  16. val numDocumentsPerPartition: Int = math.floor(partitionSizeInBytes.toFloat / avgObjSizeInBytes).toInt
  17. val numberOfSamples = math.floor(samplesPerPartition * count / numDocumentsPerPartition.toFloat).toInt
  18.  
  19. if (numDocumentsPerPartition >= count) {
  20. MongoSinglePartitioner.partitions(connector, readConfig, pipeline)
  21. } else {
  22. val samples = connector.withCollectionDo(readConfig, {
  23. coll: MongoCollection[BsonDocument] =>
  24. coll.aggregate(List(
  25. Aggregates.`match`(matchQuery),
  26. Aggregates.sample(numberOfSamples),
  27. Aggregates.project(Projections.include(partitionKey)),
  28. Aggregates.sort(Sorts.ascending(partitionKey))
  29. ).asJava).allowDiskUse(true).into(new util.ArrayList[BsonDocument]()).asScala
  30. })
  31. def collectSplit(i: Int): Boolean = (i % samplesPerPartition == 0) || !matchQuery.isEmpty && i == count - 1
  32. val rightHandBoundaries = samples.zipWithIndex.collect {
  33. case (field, i) if collectSplit(i) => field.get(partitionKey)
  34. }
  35. val addMinMax = matchQuery.isEmpty
  36. val partitions = PartitionerHelper.createPartitions(partitionKey, rightHandBoundaries, PartitionerHelper.locations(connector), addMinMax)
  37. if (!addMinMax) PartitionerHelper.setLastBoundaryToLessThanOrEqualTo(partitionKey, partitions)
  38. partitions
  39. }
  40.  
  41. case Failure(ex: MongoCommandException) if ex.getErrorMessage.endsWith("not found.") || ex.getErrorCode == 26 =>
  42. logInfo(s"Could not find collection (${readConfig.collectionName}), using a single partition")
  43. MongoSinglePartitioner.partitions(connector, readConfig, pipeline)
  44. case Failure(e) =>
  45. logWarning(s"Could not get collection statistics. Server errmsg: ${e.getMessage}")
  46. throw e
  47. }
  48. }
  49. // scalastyle:on cyclomatic.complexity
  50. }

    上面这段是connector中的代码,作用是划分partition,sample的大小不会影响数据准确性,只会影响性能。改成1可以避免这个错误。

2、带验证的数据读写,不能初始化类。

  有些时候我会将部分数据读出来,修改后更新回原collection,但是MongoSpark.write操作只能写入到一张不存在的表中,不能进行upsert,所以需要在分发任务的时候序列化一个(val dbColl: MongoCollection[Document] = db.getCollection("")),把它传到每个task中,这样我就可以处理完一部分数据之后直接用这个MongoCollection写回到表里,rdd.foreach(x => {????  dbColl.replaceOne(eqq("_id", y.get("_id")), y, new UpdateOptions().upsert(true))})。这个在没有认证的时候是可以的,但是在有认证的情况下会报不能初始化类的错误,仔细看错误路径发现报错部分在dbColl.replaceOne这句。经过若干次尝试,发现:

  a) 如果在rdd.foreach之前使用val mongoURI = new MongoClientURI(uri)会报MongoClientURI不能被序列化的错。

  b) 如果这个写在main()之前,会出现不能初始化类的错误。

  c) 如果这个写在里面,但是rdd.foreach中用到了外面声明的一个Calendar,也会报不能初始化类的错误。

  d) 把Calendar转化为字符串,val mongoURI = new MongoClientURI(uri)都写在foreach里面,可以正确执行。

  得出结论如下:

  好多乱七八糟的类不能被序列化,不能被序列化的东西需要分发的话就会报这个错误。但是知道了原理还得想个解决方案,毕竟每条数据都创建一个mongoclient实在有点怪怪的,所以最后决定使用foreachPartition,具体如下:

  1. val rdd = MongoSpark.builder().sparkSession(spark).build().toRDD()
  2. // val df = MongoSpark.builder().sparkSession(spark).build.toDF
  3. // MongoSpark.save(df.write)
  4. rdd.cache()
  5. println(rdd.count())
  6. val uri = s"mongodb://${user}:${passwd}@192.168.12.161:27017/?authSource=${authDB}"
  7. val uri2 = s"mongodb://${config.getString("mongo.backup.user")}:${config.getString("mongo.backup.passwd")}@192.168.12.160:27017/?authSource=${config.getString("mongo.backup.authDB")}"
  8. rdd.foreachPartition { x => {
  9. val mongoURI = new MongoClientURI(uri)
  10. val mongo = new MongoClient(mongoURI)
  11. val db = mongo.getDatabase("wenshu")
  12. val dbColl = db.getCollection("origin")
  13.  
  14. //val mongoURI2 = new MongoClientURI(s"mongodb://${config.getString("mongo.backup.user")}:${config.getString("mongo.backup.user")}@192.168.12.160:27017/?authSource=${config.getString("mongo.backup.user")}")
  15. val mongoURI2 = new MongoClientURI(uri2)
  16. val mongo2 = new MongoClient(mongoURI2)
  17. val db2 = mongo2.getDatabase("wenshu")
  18. val dbColl2 = db2.getCollection(backName)
  19.  
  20. x.foreach { y =>
  21. dbColl.replaceOne(eqq("_id", y.get("_id")), y, new UpdateOptions().upsert(true))
  22. dbColl2.insertOne(y)
  23. }
  24. mongo.close
  25. mongo2.close
  26. } }

  

MongoDB With Spark遇到的2个错误,不能初始化和sample重复的key的更多相关文章

  1. c++中深层复制(浅层复制运行错误)成功运行-----sample

    下面随笔给出c++中深层复制(浅层复制运行错误)成功运行------sample. 浅层复制与深层复制 浅层复制 实现对象间数据元素的一一对应复制. 深层复制 当被复制的对象数据成员是指针类型时,不是 ...

  2. Mongodb集群搭建过程及常见错误

    Replica Sets MongoDB 支持在多个机器中通过异步复制达到故障转移和实现冗余.多机器中同一时刻只 有一台是用于写操作.正是由于这个情况,为 MongoDB 提供了数据一致性的保障.担当 ...

  3. spark mllib配置pom.xml错误 Multiple markers at this line Could not transfer artifact net.sf.opencsv:opencsv:jar:2.3 from/to central (https://repo.maven.apache.org/maven2): repo.maven.apache.org

    刚刚spark mllib,在maven repository网站http://mvnrepository.com/中查询mllib后得到相关库的最新dependence为: <dependen ...

  4. Spark随机深林扩展—OOB错误评估和变量权重

    本文目的 当前spark(1.3版)随机森林实现,没有包括OOB错误评估和变量权重计算.而这两个功能在实际工作中比较常用.OOB错误评估可以代替交叉检验,评估模型整体结果,避免交叉检验带来的计算开销. ...

  5. Mongodb解决不能连接到服务器的错误

    注:这次解决的这个问题的前提是之前打开MongoDB之后,再次使用的时候无法连接了(使用mongod和mongo都不对) 闲话:遇到这种问题真是让人恼火,所以说句sun of beach,好了~爽 正 ...

  6. MongoDB,HDFS, Spark to 电影推荐

    http://www.infoq.com/cn/news/2014/12/mongdb-spark-movie-recommend MovieWeb是一个电影相关的网站,它提供的功能包括搜索电影信息. ...

  7. MongoDB的“not master and slaveok=false”错误解决

    在客户端操作MongoDB时经常会如下错误: SECONDARY> show collections; Fri Jul :: uncaught exception: error: { } 原因是 ...

  8. MongoDB:数据导入CSV文件之错误记录

    测试主机1:Windows 10,MongoDB 3.6.3,WPS 10.1,Notepad++ 7.5.3, 测试主机2:Ubuntu 16.04,MongoDB 4, 今天测试了将数据从文件—— ...

  9. spark出现task不能序列化错误的解决方法 org.apache.spark.SparkException: Task not serializable

    import org.elasticsearch.cluster.routing.Murmur3HashFunction; import org.elasticsearch.common.math.M ...

随机推荐

  1. 催希凡javaweb 学习28天

    看到这样的博客,自己也在看传智播客的视频,收藏一下 催希凡javaweb 学习28天 http://www.cnblogs.com/Prozhu/category/824899.html

  2. pycharm快捷键帮助文档Keymap Reference

    前面我们已经安装了pycharm,为了提升效率,我们一般会用到快捷键操作,pycharm有哪些快捷键呢?Pycharm中打开Help->Keymap Reference可查看默认快捷键帮助文档, ...

  3. 小程序升级实时音视频录制及播放能力,开放 Wi-Fi、NFC(HCE) 等硬件连接功能

    “ 小程序升级实时音视频录制及播放能力,开放 Wi-Fi.NFC(HCE) 等硬件连接功能.同时提供按需加载.自定义组件和更多访问层级等新特性,增强了第三方平台的能力,以满足日趋丰富的业务需求.” 0 ...

  4. MySQL复制异常大扫盲:快速溯源与排查错误全解

    MySQL复制异常大扫盲:快速溯源与排查错误全解https://mp.weixin.qq.com/s/0Ic8BnUokyOj7m1YOrk1tA 作者介绍王松磊,现任职于UCloud,从事MySQL ...

  5. jvm - 类的初始化过程

    我们知道,我们写的java代码称为源码,想要能够被jvm执行首先需要编译成.class文件,那么编译完到使用又都经理的哪些阶段呢?主要分为以下三个阶段: 加载:查找并加载类的二进制数据(.class文 ...

  6. C语言数据类型运算法则

    整形与整形运算得到的还是整形 printf("%d\n",1/3); //0 printf("%d\n",1+2); //3 整形与浮点型运算得到浮点型数据 p ...

  7. js中的offsetLeft和style.left

    (1)style.left是带单位"px"的,而offsetLeft没有单位,另外,style.left必须是内联样式,或者在JS中通过style.left赋值,否则取得的将为空字 ...

  8. iot-hub物管理bug

    物管理中,物绑定证书,如果证书被删除,将会出错 初始化用到 证书编码,证书为null时,null.code报错

  9. 对k8s service的一些理解

    服务service service是一个抽象概念,定义了一个服务的多个pod逻辑合集和访问pod的策略,一般把service称为微服务 举个例子一个a服务运行3个pod,b服务怎么访问a服务的pod, ...

  10. 如何打印一棵树(Java)

    1.有一棵多叉树,将它打印出来. import java.util.LinkedList; /** * 需求:按层打印一棵树 * 说明:树是保存在一个链表中 * created by wangjunf ...