无法创建复合索引,卡在INSTALLED

时间:2016-02-26 16:11:34

标签: amazon-dynamodb titan gremlin

我无法创建索引。我的Gremlin代码如下:

usernameProperty = mgmt.getPropertyKey('username')
usernameIndex = mgmt.buildIndex('byUsernameUnique', Vertex.class).addKey(usernameProperty).unique().buildCompositeIndex()
mgmt.setConsistency(usernameIndex, ConsistencyModifier.LOCK)
mgmt.commit()

收到两个错误后不久:

  

18:04:57 ERROR com.thinkaurelius.titan.graphdb.database.management.ManagementLogger - 从缓存中驱逐[1 @ 0a00009d2537-ip-10-0-0-1572],但等待交易结束的时间太长。过时的交易警报:[standardtitantx [0x6549ce71]]   18:04:57 ERROR com.thinkaurelius.titan.graphdb.database.management.ManagementLogger - 从缓存中驱逐[1 @ 0a00009d2537-ip-10-0-0-1572]但等待交易结束的时间太长。过时的交易警报:[standardtitantx [0x2a2815cc],standardtitantx [0x025dc2c0]]

索引的状态停留在INSTALLED

usernameIndex.getIndexStatus(usernameProperty)
==>INSTALLED

我读到失败的实例可能会导致问题,但检查正在运行的实例只显示一个:

mgmt.getOpenInstances()
==>0a00009d3011-ip-10-0-0-1572(current)

我还尝试发布REGISTER_INDEX操作,该操作也会从事务缓存中逐出,并显示类似的错误消息:

mgmt.updateIndex(usernameIndex, SchemaAction.REGISTER_INDEX).get()
mgmt.commit()

我也尝试过多次重启服务器。

注册过程似乎只是超时,造成了一次驱逐"来自事务缓存。我已经等了48个小时,以确保它不是一个缓慢的过程。对Titan的正常读取,写入和相关提交似乎正常工作,我只是无法创建此索引。我被困了,还有什么我可以尝试的吗?有没有办法延长该事务的超时?

我使用DynamoDB后端运行Titan 1.0.0(使用AWS提供的CloudFormation template进行设置)。

编辑: 这是我通过添加@ M-T-A建议的awaitGraphStatus步骤粘贴到Gremlin的完整命令:

mgmt = graph.openManagement();
usernameIndex = mgmt.getPropertyKey('usernameIndex');
mgmt.buildIndex('byUsername',Vertex.class).addKey(usernameIndex).unique().buildCompositeIndex();
// I have tried with and without a commit here: mgmt.commit();
mgmt.awaitGraphIndexStatus(graph, 'byUsername').status(SchemaStatus.REGISTERED).timeout(10, java.time.temporal.ChronoUnit.MINUTES).call();

这会导致以下错误:

  

显示java.lang.NullPointerException       at com.thinkaurelius.titan.graphdb.database.management.GraphIndexStatusWatcher.call(GraphIndexStatusWatcher.java:52)       at com.thinkaurelius.titan.graphdb.database.management.GraphIndexStatusWatcher.call(GraphIndexStatusWatcher.java:18)       at java_util_concurrent_Callable $ call.call(Unknown Source)       在org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)       在org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:110)       在org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:114)       在groovysh_evaluate.run(groovysh_evaluate:3)       在org.codehaus.groovy.vmplugin.v7.IndyInterface.selectMethod(IndyInterface.java:215)       在org.codehaus.groovy.tools.shell.Interpreter.evaluate(Interpreter.groovy:69)       在org.codehaus.groovy.tools.shell.Groovysh.execute(Groovysh.groovy:185)       在org.codehaus.groovy.tools.shell.Shell.leftShift(Shell.groovy:119)       在org.codehaus.groovy.tools.shell.ShellRunner.work(ShellRunner.groovy:94)

我还要注意,禁用和删除索引的例程也失败了。

mgmt = graph.openManagement()
theIndex = mgmt.getGraphIndex('byUsername')
mgmt.updateIndex(theIndex, SchemaAction.DISABLE_INDEX).get()
mgmt.commit()
mgmt.awaitGraphIndexStatus(graph, 'byUsername').status(SchemaStatus.DISABLED).timeout(10, java.time.temporal.ChronoUnit.MINUTES).call();
m = graph.openManagement()
i = m.getGraphIndex('byUsername')
m.updateIndex(i, SchemaAction.REMOVE_INDEX).get()
m.commit()
  

19:26:26 ERROR com.thinkaurelius.titan.graphdb.database.management.ManagementLogger - 从缓存中驱逐[1 @ ac1f3fa810472-ip-172-31-63-1681],但等待交易关闭的时间太长。过时的交易警报:[standardtitantx [0x2314cd97],standardtitantx [0x39f8adc0],standardtitantx [0x09de1b85]]

编辑2: 尝试在同一事务中创建新的属性键和索引工作!但这是否意味着我无法在现有属性键上创建索引?

graph.tx().rollback();
mgmt = graph.openManagement();
indexName = 'byUsernameTest2';
propertyKeyName = 'testPropertyName2';
propertyKey = mgmt.makePropertyKey(propertyKeyName).dataType(String.class).cardinality(Cardinality.SINGLE).make();
mgmt.buildIndex(indexName,Vertex.class).addKey(propertyKey).buildCompositeIndex();
mgmt.commit();
graph.tx().commit();
mgmt.awaitGraphIndexStatus(graph, indexName).status(SchemaStatus.REGISTERED).timeout(10, java.time.temporal.ChronoUnit.MINUTES).call();
mgmt.commit();

暂停后,结果是:

  

此管理系统实例已关闭

尝试获取新索引会导致:

mgmt = graph.openManagement();
index = mgmt.getGraphIndex('byUsernameTest2');
propkey = mgmt.getPropertyKey('testPropertyName2');
index.getIndexStatus(propkey);
  

==> ENABLED

2 个答案:

答案 0 :(得分:4)

如果你正在运行多个Titan实例,你应该知道他们需要在索引可用之前进行协调。

此外,交易管理存在各种细微之处,交易将在何种情况下保持开放;我相信Titan 1.0.0在这方面没有来自TinkerPop的最新消息。您是否尝试过在启动后立即创建索引?

最后,索引创建过程会有所不同,具体取决于之前是否使用过索引的属性键。您是在尝试索引新密钥还是现有密钥?

答案 1 :(得分:3)

您需要等待Titan和DynamoDB才能注册索引。你可以这样做:

ManagementSystem.awaitGraphIndexStatus(graph, propertyKeyIndexName)
                    .status(SchemaStatus.REGISTERED)
                    .timeout(10, java.time.temporal.ChronoUnit.MINUTES) // set timeout to 10 min
                    .call();

默认超时通常不够长,因此您可以将其增加到10分钟,通常可以使用Dynamo备份。

仅当索引处于“已注册”状态时,才能执行重新索引。完成重新索引后,您需要等到它已启用。通过重用上面的代码示例并将状态更改为ENABLED。

有关详细信息,请参阅docs

修改

让我一直在Berkeley和Dynamo DB后端分享与我合作的代码。

    graph.tx().rollback(); //Never create new indexes while a transaction is active
    TitanManagement mgmt=graph.openManagement();
    PropertyKey propertyKey=getOrCreatePropertyKeyIfNotExist(mgmt, propertyKeyName);
    String indexName = makePropertyKeyIndexName(propertyKey);

    if (mgmt.getGraphIndex(indexName)==null) { 
        mgmt.buildIndex(indexName, Vertex.class).addKey(propertyKey).buildCompositeIndex();
        mgmt.commit(); // you MUST commit mgmt
        graph.tx().commit(); // and commit the transaction too
        ManagementSystem.awaitGraphIndexStatus(graph, indexName).status(SchemaStatus.REGISTERED).call();
    }else { // already defined.
        mgmt.rollback();
        graph.tx().rollback();
    }

private static PropertyKey getOrCreatePropertyKeyIfNotExist(TitanManagement mgmt, String s) {
    PropertyKey key = mgmt.getPropertyKey(s);
    if (key != null)
        return key;
    else
        return mgmt.makePropertyKey(s).dataType(String.class).make();
}

private static String makePropertyKeyIndexName(PropertyKey pk) {
    return pk.name() + Tokens.INDEX_SUFFIX;
}

从我看到的错误来看,似乎Titan无法获得索引,这意味着您正在等待甚至没有定义的索引。看看导致错误here的行。

确保您将正确的索引名称传递给awaitGraphIndexStatus