Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.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
Python3:cassandra.cluster.NoHostAvailable:(“无法使用keyspace';test';,[';127.0.0.1';]”连接到任何服务器,当使用execute#async future时_Python_Python 3.x_Cassandra_Cassandra 3.0 - Fatal编程技术网

Python3:cassandra.cluster.NoHostAvailable:(“无法使用keyspace';test';,[';127.0.0.1';]”连接到任何服务器,当使用execute#async future时

Python3:cassandra.cluster.NoHostAvailable:(“无法使用keyspace';test';,[';127.0.0.1';]”连接到任何服务器,当使用execute#async future时,python,python-3.x,cassandra,cassandra-3.0,Python,Python 3.x,Cassandra,Cassandra 3.0,我试图从一个特定的表中从Cassandra获取数据,并在做了一些更改后尝试将其插入Cassandra中的另一个表中。这两个表都位于键空间“test”中。当我试图从第一个表中获取数据时,一切正常,它能够获取数据。但是,在处理第一个查询输出的未来处理程序中,我试图将数据插入同一Cassandra实例下的另一个表中,但它获取失败。我从应用程序收到一个错误,声明“cassandra.cluster.NoHostAvailable:(“无法使用键空间'test',['127.0.0.1']连接到任何服务器

我试图从一个特定的表中从Cassandra获取数据,并在做了一些更改后尝试将其插入Cassandra中的另一个表中。这两个表都位于键空间“test”中。当我试图从第一个表中获取数据时,一切正常,它能够获取数据。但是,在处理第一个查询输出的未来处理程序中,我试图将数据插入同一Cassandra实例下的另一个表中,但它获取失败。我从应用程序收到一个错误,声明“cassandra.cluster.NoHostAvailable:(“无法使用键空间'test',['127.0.0.1']连接到任何服务器”)。我不确定我会错在哪里

import threading
from threading import Event
from cassandra.query import SimpleStatement
from cassandra.cluster import Cluster


hosts=['127.0.0.1']
keyspace="test"
thread_local = threading.local()
cluster_ = Cluster(hosts)
def get_session():
    if hasattr(thread_local, "cassandra_session"):
        print("got session from threadlocal")
        return thread_local.cassandra_session
    print(" Connecting to Cassandra Host " + str(hosts))
    session_ = cluster_.connect(keyspace)
    print(" Connecting and creating session to Cassandra KeySpace " + keyspace)
    thread_local.cassandra_session = session_
    return session_


class PagedResultHandler(object):

    def __init__(self, future):
        self.error = None
        self.finished_event = Event()
        self.future = future
        self.future.add_callbacks(
            callback=self.handle_page,
            errback=self.handle_error)

    def handle_page(self, rows):
        for row in rows:
            process_row(row)

        if self.future.has_more_pages:
            self.future.start_fetching_next_page()
        else:
            self.finished_event.set()

    def handle_error(self, exc):
        self.error = exc
        self.finished_event.set()

def process_row(row):
    print(row)
    session_ = get_session()
    stmt = session_.prepare(
        "INSERT INTO test.data(customer,snr,rttt, event_time) VALUES (?,?,?,?)")
    results = session_.execute(stmt,
                               [row.customer, row.snr, row.rttt,row.created_time])
    print("Done")

session = get_session()
query = "select * from test.data_log"
statement = SimpleStatement(query, fetch_size=1000)
future = session.execute_async(statement)
handler = PagedResultHandler(future)
handler.finished_event.wait()
if handler.error:
    raise handler.error
cluster_.shutdown()
但是,当我尝试执行python文件时,应用程序从“process_row”方法的getSession()调用抛出错误“cassandra.cluster.NoHostAvailable:(“无法使用键空间'test',['127.0.0.1'])。显然,第一次打电话给卡桑德拉是成功的,没有任何问题。没有连接问题,Cassandra实例在本地运行良好。我能够使用cqlsh查询数据。如果我在未来处理程序之外调用process_row方法,那么一切都正常工作,我不确定需要做什么才能从未来处理程序实现

Connecting to Cassandra Host ['127.0.0.1']
Connecting and creating session to Cassandra KeySpace test
Row(customer='abcd', snr=100, rttt=121, created_time=datetime.datetime(2020, 8, 8, 2, 26, 51))
 Connecting to Cassandra Host ['127.0.0.1']
Traceback (most recent call last):
  File "test/check.py", , in <module>
    raise handler.error
  File "cassandra/cluster.py", line 4579, in cassandra.cluster.ResponseFuture._set_result
  File "cassandra/cluster.py", line 4777, in cassandra.cluster.ResponseFuture._set_final_result
  File "test/check.py"",  in handle_page
    process_row(row)
  File "test/check.py"",  in process_row
    session_ = get_session()
  File "/test/check.py"", in get_session
    session_ = cluster_.connect(keyspace)
  File "cassandra/cluster.py", line 1715, in cassandra.cluster.Cluster.connect
  File "cassandra/cluster.py", line 1772, in cassandra.cluster.Cluster._new_session
  File "cassandra/cluster.py", line 2553, in cassandra.cluster.Session.__init__
cassandra.cluster.NoHostAvailable: ("Unable to connect to any servers using keyspace 'test'", ['127.0.0.1'])

Process finished with exit code 1
连接到Cassandra主机['127.0.0.1']
连接并创建会话到Cassandra密钥空间测试
行(customer='abcd',snr=100,rttt=121,created_time=datetime.datetime(2020,8,8,2,26,51))
正在连接到Cassandra主机['127.0.0.1']
回溯(最近一次呼叫最后一次):
文件“test/check.py”,位于
raise handler.error
文件“cassandra/cluster.py”,第4579行,位于cassandra.cluster.ResponseFuture.\u set\u result
文件“cassandra/cluster.py”,第4777行,位于cassandra.cluster.ResponseFuture.\u set\u final\u result\u
文件“test/check.py”,位于句柄页面中
处理单元行(行)
文件“test/check.py”,位于进程行中
会话=获取会话()
获取会话中的文件“/test/check.py”
会话=群集连接(键空间)
文件“cassandra/cluster.py”,第1715行,位于cassandra.cluster.cluster.connect中
文件“cassandra/cluster.py”,第1772行,在cassandra.cluster.cluster.\u new\u会话中
文件“cassandra/cluster.py”,第2553行,位于cassandra.cluster.Session.\uu init__
cassandra.cluster.NoHostAvailable:(“无法使用键空间'test',['127.0.0.1']连接到任何服务器)
进程已完成,退出代码为1

好,因此卡桑德拉建议:

  • 每个键空间最多使用一个会话,或者使用单个会话并在查询中明确指定键空间

在代码中,每次读取查询检索到一些行时,都会尝试创建会话

为了强制代码最多使用一个会话,我们可以创建一个队列,子线程将行发送到主线程,主线程通过执行insert查询进一步处理行。我们在主线程中执行此操作,因为我在子线程中执行查询时遇到了问题

callback_queue = Queue()
session = cluster_.connect(keyspace)
session.row_factory = dict_factory # because queue doesn't accept a Row instance


class PagedResultHandler(object):

    ...

    def handle_page(self, rows):
        for row in rows:
            callback_queue.put(row) # here we pass the row as a dict to the queue
        ...

def process_rows():
    while True:
        try:
            row = callback_queue.get() # here we retrieve the row as a dict from the child thread
            stmt = session.prepare(
                "INSERT INTO test.data(customer,snr,rttt, event_time) VALUES (?,?,?,?,?)")
            results = session.execute(stmt,
                                       [row['customer'], row['snr'], row['rttt'], row['created_time']])
            print("Done")
        except Empty:
            pass

query = "select * from test.data_log"
statement = SimpleStatement(query, fetch_size=1000)
future = session.execute_async(statement)
handler = PagedResultHandler(future)
process_rows() # for now the code will hang here because we have an infinite loop in this function
handler.finished_event.wait()
if handler.error:
    raise handler.error
cluster_.shutdown()

这将使它工作,但我将替换while True,否则将进入无限循环。

好的,在这种情况下,我们可以做两件事,我们可以使用多线程和批插入。我认为如果我们不需要批插入并行性,因为这将使客户端的速度足够快。多线程不会增加太多由于它不是cpu密集型任务,因此速度更快

session = cluster_.connect(keyspace)
session.row_factory = dict_factory


class Fetcher:

    def __init__(self, session):
        self.session = session
        query = "select * from test.data_log"
        self.statement = SimpleStatement(query, fetch_size=1000)

    def run(self):
        rows = self.session.execute(self.statement)

        temp_rows = []
        total = 0
        for row in rows:
            temp_rows.append(row)
            if len(temp_rows) == 1000:
                handler = PagedResultHandler(self.session, temp_rows)
                handler.start()
                temp_rows = []

        handler = PagedResultHandler(self.session, temp_rows)
        handler.start()

    def handle_error(self, err=None):
        print(err)


class PagedResultHandler(threading.Thread):

    def __init__(self, session, rows):
        super().__init__()
        self.session = session
        self.error = None
        self.rows = rows
        self.finished_event = Event()

    def run(self):
        batch = BatchStatement(consistency_level=ConsistencyLevel.QUORUM)
        stmt = session.prepare("INSERT INTO test.data(id, customer,snr,rttt, event_time) VALUES (?,?,?,?,?)")
        for row in self.rows:
            batch.add(stmt, [1, row['customer'], row['snr'], row['rttt'], row['created_time']])
        results = session.execute(batch)
        print(results)


Fetcher(session).run()

这个脚本确实可以进行批插入和多线程处理,但多线程似乎没有必要。

如果我可以问的话,您使用的是哪种Python版本?Iam使用Python 3.7参考:我已经投票并接受了您的答案。我还获得了针对这个问题的奖金。不过,我确实有一个相对较大的数据集,我确实希望让这些插入并行完成以加快过程。您给我的解决方案不能帮助我以有效的方式将包含数百万条记录的完整表转储到另一个表中。您可以查看。这将让您了解为什么我一直在为每个任务创建多个会话。我们如何在python中通过在代码的并行性方面进行批处理?在最初的尝试和这次尝试之间有很大的区别。在这里,通过使Fetcher成为一个单独的线程,您不会获得任何好处。我同意批处理部分,它显著提高了提供的权限。如果您根据分区键批处理所有记录,则盲批处理不会有多大帮助。also对于行处理,您带来了并行性,这无疑提高了性能。我仍在试图找出我最初的方法不起作用的原因,即使您与进程共享同一个会话。\u行(row):函数它似乎抛出“没有可用的主机: