Spark Mongo连接器,MongoShardedPartitioner不起作用

时间:2019-01-07 21:34:53

标签: mongodb apache-spark pyspark sharding mongodb-cluster

出于测试目的,我配置了一个4节点集群,每个集群都有一个Spark Worker和一个MongoDB Shard。这些是详细信息:

  • 四个Debian 9服务器(名为Visa0,Visa1,Visa2,Visa3)
  • 4个节点上的Spark(v2.4.0)集群(visa1:主节点,visa0..3:从节点)
  • MongoDB(v3.2.11)分片群集包含4个节点(在Visa1..3上设置了配置服务器副本,在Visa1上设置了mongos,在分片服务器上设置了Visa0..3)
  • 我正在使用与“ spark-shell --packages”一起安装的MongoDB Spark连接器 org.mongodb.spark:mongo-spark-connector_2.11:2.4.0“

使用MongoShardedPartitioner配置SparkSession时,从数据库加载的每个数据帧都是空的,尽管该数据帧架构已正确获取。

可以在spark-defaults.conf文件中完成配置,也可以在SparkSession构建器中使用.config("spark.mongodb.input.partitioner" ,"MongoShardedPartitioner")来复制配置。

使用MongoShardedPartitioner,df.count()== 0:

./pyspark --master "spark://visa1:7077" --packages "org.mongodb.spark:mongo-spark-connector_2.11:2.4.0"

...

Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 2.4.0
      /_/

Using Python version 3.5.3 (default, Sep 27 2018 17:27:03)
SparkSession available as 'spark'.
>>> spark2 = SparkSession \
...   .builder \
...   .appName("myApp") \
...   .config("spark.mongodb.input.partitioner" ,"MongoShardedPartitioner") \
...   .getOrCreate()
>>> 
>>> df2 = spark2.read.format("com.mongodb.spark.sql.DefaultSource") \
... .option("uri", "mongodb://visa1/email.emails") \
... .option("pipeline", '[ {"$match": {"mailbox": /^\/root\/pst_export\/albert_meyers_000_1_1.export/}} ]') \
... .load()
>>>                                                                             
>>> df2.count()
0  

但是在不指定分区程序的情况下可以正常工作:

./pyspark --master "spark://visa1:7077" --packages "org.mongodb.spark:mongo-spark-connector_2.11:2.4.0"

...

Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 2.4.0
      /_/

Using Python version 3.5.3 (default, Sep 27 2018 17:27:03)
SparkSession available as 'spark'.
>>> spark2 = SparkSession \
...   .builder \
...   .appName("myApp") \
...   .getOrCreate()
>>> 
>>> df2 = spark2.read.format("com.mongodb.spark.sql.DefaultSource") \
... .option("uri", "mongodb://visa1/email.emails") \
... .option("pipeline", '[ {"$match": {"mailbox": /^\/root\/pst_export\/albert_meyers_000_1_1.export/}} ]') \
... .load()
2019-01-07 22:7:33 WARN  Utils:66 - Truncated the string representation of a plan since it was too large. This behavior can be adjusted by setting 'spark.debug.maxToStringFields' in SparkEnv.conf.
>>> 
>>> df2.count()
1162  

问题:

  • 如何知道默认情况下配置了哪个分区程序?
  • 在这种情况下如何使用MongoShardedPartitioner

预先感谢

2019年1月13日:推荐的解决方法

如下所述,似乎MongoShardedPartitioner不支持将哈希索引用作分片索引。但是,我需要一个哈希索引来将块均匀地分布在节点上,而与时间无关(我想使用_id将按时间顺序分布)。

我的解决方法是在数据库中创建一个新字段,并使用日期存储区的md5哈希值对它进行索引(作为普通索引)并将其用作分片索引。

现在,代码可以正常工作了:

Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /__ / .__/\_,_/_/ /_/\_\   version 2.4.0
      /_/

Using Python version 3.5.3 (default, Sep 27 2018 17:25:39)
SparkSession available as 'spark'.
>>> 
>>> 
>>> spark2 = SparkSession \
...   .builder \
...   .appName("myApp") \
...   .config("spark.mongodb.input.partitioner" ,"MongoShardedPartitioner") \
...   .config("spark.mongodb.input.partitionerOptions.shardkey", "datebuckethash") \
...   .getOrCreate()
>>> 
>>> 
>>> df2 = spark2.read.format("com.mongodb.spark.sql.DefaultSource") \
... .option("uri", "mongodb://visa1/email.emails") \
... .option("pipeline", '[ {"$match": {"mailbox": /^\/root\/pst_export\/albert_meyers_000_1_1.export/}} ]') \
... .load()

2019-01-13 11:19:31 WARN  Utils:66 - Truncated the string representation of a plan since it was too large. This behavior can be adjusted by setting 'spark.debug.maxToStringFields' in SparkEnv.conf.
>>> 
>>> df2.count()
1162   

1 个答案:

答案 0 :(得分:0)

很抱歉听到您的连接器有问题。

  

如何知道默认情况下配置了哪个分区程序?

有关分区程序的信息可以在Spark connector documentation site上找到。如果您觉得有任何遗漏或不清楚的地方,请在Docs jira project中提交票证,这确实可以为将来的用户提供帮助!

默认分区程序是MongoSamplePartitioner周围的薄包装。它基于对集合的统计采样将集合分成大小不同的分区。

  

在这种情况下如何使用MongoShardedPartitioner

MongoShardedPartitioner使用shardKey生成分区。默认情况下,它将使用_id作为密钥。您可能需要配置该值。

注意MongoShardedPartitioner 不支持散列分片,因为目前尚无法根据散列值查询集合-因此,在检索分区时它将无法返回结果。我添加了DOCS-12345来更新文档。

似乎您的设置中存在一个问题,MongoShardedPartitioner无法按预期方式对集合进行分区,并返回0个结果。由于模式推论是如何查询集合的,因此模式推论仍将起作用。如果不是配置/哈希分键问题,请发布Spark jira project中的错误,我们将帮助您找出原因并为您发布修复程序。

相关问题