Java 无法更新6m+;couchbase server社区版3.0.1上的文档

Java 无法更新6m+;couchbase server社区版3.0.1上的文档,java,couchbase,Java,Couchbase,我正在尝试更新couchbase server community edition 3.0.1服务器集群中的600多万个文档。我正在使用最新的JavaSDK,并尝试了各种方法,可以从视图中读取一批文档,更新它们并将它们替换回bucket 在我看来,随着流程的推进,吞吐量变得太慢,甚至不到300 op/s。我尝试了很多方法,使用批量操作方法(使用Observable)来加快速度,但都没有成功。我甚至让进程运行了几个小时,后来却发现超时异常 我尝试的最后一个选项是从视图中将所有文档ID读入一个临时文

我正在尝试更新couchbase server community edition 3.0.1服务器集群中的600多万个文档。我正在使用最新的JavaSDK,并尝试了各种方法,可以从视图中读取一批文档,更新它们并将它们替换回bucket

在我看来,随着流程的推进,吞吐量变得太慢,甚至不到300 op/s。我尝试了很多方法,使用批量操作方法(使用Observable)来加快速度,但都没有成功。我甚至让进程运行了几个小时,后来却发现超时异常

我尝试的最后一个选项是从视图中将所有文档ID读入一个临时文件,以便我可以读回该文件并更新记录。但是,在3小时后,仅从视图中读取了170万个ID(仅约157项/秒!),DB给出了超时异常

注意couchbase集群包含3台服务器(Ubuntu14.04),每个服务器有8个内核、24GB RAM和1TB SSD,运行更新数据的java代码位于同一个网络中,有4个内核、16GB RAM和1TB SSD。并且此群集上没有运行其他负载

看起来,从服务器的视图中读取所有ID都是不可能的。我检查了网络吞吐量,数据库服务器仅以1mbps的速度提供数据

下面是用于从视图中读取所有文档ID的示例代码:

final Bucket statsBucket = db.getStatsBucket();
int skipCount = 0;
int limitCount = 10000;

System.out.println("reading stats ids ...");

try (DataOutputStream out = new DataOutputStream(new FileOutputStream("rowIds.tmp")))
{
    while (true)
    {
        ViewResult result = statsBucket.query(ViewQuery.from("Stats", "AllLogs").skip(skipCount).limit(limitCount).stale(Stale.TRUE));

        Iterator<ViewRow> rows = result.iterator();

        if (!rows.hasNext())
        {
            break;
        }

        while (rows.hasNext())
        {
            out.writeUTF(rows.next().id());
        }

        skipCount += limitCount;
        System.out.println(skipCount);
    }
}
final Bucket statsBucket=db.getStatsBucket();
int skipCount=0;
int limitCount=10000;
System.out.println(“读取统计ID…”);
try(DataOutputStream out=newdataoutputstream(newfileoutputstream(“rowIds.tmp”))
{
while(true)
{
ViewResult result=statsBucket.query(ViewQuery.from(“Stats”,“alllog”).skip(skipCount).limitCount(limitCount).stale(stale.TRUE));
迭代器行=result.Iterator();
如果(!rows.hasNext())
{
打破
}
while(rows.hasNext())
{
out.writeUTF(rows.next().id());
}
skipCount+=limitCount;
系统输出打印项次(skipCount);
}
}
即使使用批量操作(可观察)方法,我也尝试过,但没有任何成功。还尝试将限制计数更改为1000(但不限制java应用程序在一段时间后会发疯,甚至SSH也会停止响应)


有什么方法可以做到这一点吗?

我找到了解决方案。ViewQuery.skip()方法不是真正的跳过,不应该用于分页。skip()方法只会从视图开始读取所有数据,并且只会在读取记录数后才开始输出,就像链表一样

解决方案是使用startKey()和startKeyDocId()。进入这些方法的ID是您读取的最后一个项的ID。从这里获得此解决方案:

因此,读取视图中所有项目的最终代码是:

final Bucket statsBucket = db.getStatsBucket();
int limitCount = 10000;
int skipCount = 0;

System.out.println("reading stats ids ...");

try (DataOutputStream out = new DataOutputStream(new FileOutputStream("rowIds.tmp")))
{
    String lastKeyDocId = null;

    while (true)
    {
        ViewResult result;

        if (lastKeyDocId == null)
        {
            result = statsBucket.query(ViewQuery.from("Stats", "AllLogs").limit(limitCount).stale(Stale.FALSE));
        }
        else
        {
            result = statsBucket.query(ViewQuery.from("Stats", "AllLogs").limit(limitCount).stale(Stale.TRUE).startKey(lastKeyDocId).skip(1));
        }

        Iterator<ViewRow> rows = result.iterator();

        if (!rows.hasNext())
        {
            break;
        }

        while (rows.hasNext())
        {
            lastKeyDocId = rows.next().id();
            out.writeUTF(lastKeyDocId);
        }

        skipCount += limitCount;
        System.out.println(skipCount);
    }
}
final Bucket statsBucket=db.getStatsBucket();
int limitCount=10000;
int skipCount=0;
System.out.println(“读取统计ID…”);
try(DataOutputStream out=newdataoutputstream(newfileoutputstream(“rowIds.tmp”))
{
字符串lastKeyDocId=null;
while(true)
{
查看结果;
if(lastKeyDocId==null)
{
result=statsBucket.query(ViewQuery.from(“Stats”,“AllLogs”).limit(limitCount).stale(stale.FALSE));
}
其他的
{
result=statsBucket.query(ViewQuery.from(“Stats”,“AllLogs”).limit(limitCount).stale(stale.TRUE).startKey(lastKeyDocId).skip(1));
}
迭代器行=result.Iterator();
如果(!rows.hasNext())
{
打破
}
while(rows.hasNext())
{
lastKeyDocId=rows.next().id();
out.writeUTF(lastKeyDocId);
}
skipCount+=limitCount;
系统输出打印项次(skipCount);
}
}

对于大数据量,不要为单个更新而烦恼,只需专注于各种批量操作。已经尝试过使用批量操作方法,但也有相同的问题。示例代码只是为了简单起见,我尝试过只使用simple for loop,不使用任何线程,将100000个文档的测试数据插入到同一集群中成功实现了12K op/s。只是当记录数超过几十万条时,问题开始将吞吐量降低到极限。您尝试过多线程吗?bucket.async()get和replace与Observable相结合的方法本身使用多线程。您是否测试过限制因素是从视图读取的速度,还是返回服务器的更新速度?