Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 带有HappyBase连接池的PySpark dataframe.foreach()返回';类型错误:can';t pickle thread.lock对象';_Python_Apache Spark_Pyspark_Happybase - Fatal编程技术网

Python 带有HappyBase连接池的PySpark dataframe.foreach()返回';类型错误:can';t pickle thread.lock对象';

Python 带有HappyBase连接池的PySpark dataframe.foreach()返回';类型错误:can';t pickle thread.lock对象';,python,apache-spark,pyspark,happybase,Python,Apache Spark,Pyspark,Happybase,我有一个PySpark作业,它更新HBase中的一些对象(Spark v1.6.0;happybase v0.9) 如果我为每行打开/关闭一个HBase连接,它就可以正常工作: def process_row(row): conn = happybase.Connection(host=[hbase_master]) # update HBase record with data from row conn.close() my_dataframe.foreach(pr

我有一个PySpark作业,它更新HBase中的一些对象(Spark v1.6.0;happybase v0.9)

如果我为每行打开/关闭一个HBase连接,它就可以正常工作:

def process_row(row):
    conn = happybase.Connection(host=[hbase_master])
    # update HBase record with data from row
    conn.close()

my_dataframe.foreach(process_row)
经过数千次升级后,我们开始看到如下错误:

显然,为每个upsert打开/关闭连接效率很低。这个函数实际上只是一个适当解决方案的占位符

然后,我尝试创建一个版本的
process\u row
函数,该函数使用连接池:

pool = happybase.ConnectionPool(size=20, host=[hbase_master])

def process_row(row):
    with pool.connection() as conn:
        # update HBase record with data from row
由于某些原因,此函数的连接池版本返回错误(请参阅):

你能看出我做错了什么吗

更新 我看到并怀疑我遇到了相同的问题:Spark试图序列化
对象并将其分发给每个执行器,但此连接池对象无法在多个执行器之间共享

听起来我需要将数据集拆分为多个分区,并在每个分区中使用一个连接(请参阅)。根据文档中的一个示例,我尝试了以下方法:

def persist_to_hbase(dataframe_partition):
    hbase_connection = happybase.Connection(host=[hbase_master])
    for row in dataframe_partition:
        # persist data
    hbase_connection.close()

my_dataframe.foreachPartition(lambda dataframe_partition: persist_to_hbase(dataframe_partition))

不幸的是,它仍然返回“不能pickle thread.lock objects”错误。

说到底,happybase连接只是tcp连接,因此它们不能在进程之间共享。连接池主要适用于多线程应用程序,也适用于单线程应用程序,这些应用程序可以将连接池用作全局“连接工厂”,并进行连接重用,这可能会简化代码,因为不需要传递“连接”对象。它还使错误恢复变得更容易一些

在任何情况下,进程之间都不能共享池(它只是一组连接)。由于这个原因,试图将其序列化是没有意义的。(池使用的锁会导致序列化失败,但这只是一个症状。)

也许您可以使用一个助手,有条件地创建一个池(或连接)并将其存储为一个模块局部变量,而不是在导入时实例化它,例如

_pool = None

def get_pool():
    global _pool
    if _pool is None:
        _pool = happybase.ConnectionPool(size=1, host=[hbase_master])
    return pool

def process(...)
    with get_pool().connection() as connection:
        connection.table(...).put(...)

这将在首次使用时而不是在导入时实例化池/连接。

我无法重现此问题。您确定没有使用
持久化\u将其他内容拖动到\u hbase
?如果是的话,你能创建一个?我的意思是用最少的数据,完成Spark的初始化。乍一看,代码中有很多内容。一些数据帧?您可以提供如何创建数据帧吗?抛出can't pickle错误的主要原因是您试图通过序列化跨进程共享锁对象。另外,您可以使用my_dataframe.foreachPartition(persist_to_hbase)而不是创建额外的lamda。也看看它是否有用。谢谢@wouter。我有几分钟的时间就试试这个。我最终使用spark hbase连接器用Java重新编写了Python脚本,效果很好。
def persist_to_hbase(dataframe_partition):
    hbase_connection = happybase.Connection(host=[hbase_master])
    for row in dataframe_partition:
        # persist data
    hbase_connection.close()

my_dataframe.foreachPartition(lambda dataframe_partition: persist_to_hbase(dataframe_partition))
_pool = None

def get_pool():
    global _pool
    if _pool is None:
        _pool = happybase.ConnectionPool(size=1, host=[hbase_master])
    return pool

def process(...)
    with get_pool().connection() as connection:
        connection.table(...).put(...)