【问题标题】:Unable to create a composite index, stuck at INSTALLED无法创建复合索引,卡在 INSTALLED
【发布时间】:2016-06-09 22:51:56
【问题描述】:

我无法创建索引。我的 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 错误 com.thinkaurelius.titan.graphdb.database.management.ManagementLogger - 从缓存中逐出 [1@0a00009d2537-ip-10-0-0-1572] 但等待交易关闭的时间过长。过时交易警报:[standardtitantx[0x6549ce71]] 18:04:57 错误 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)。

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

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 在 com.thinkaurelius.titan.graphdb.database.management.GraphIndexStatusWatcher.call(GraphIndexStatusWatcher.java:52) 在 com.thinkaurelius.titan.graphdb.database.management.GraphIndexStatusWatcher.call(GraphIndexStatusWatcher.java:18) 在 java_util_concurrent_Callable$call.call(未知来源) 在 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 错误 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);

==>已启用

【问题讨论】:

  • 更多调试日志,添加到 ./conf/log4j-console.properties log4j.logger.com.thinkaurelius.titan.graphdb.database.management=DEBUG
  • 您是否存储了一个大数据集?您是否在几乎空的数据库上尝试过?

标签: amazon-dynamodb titan gremlin


【解决方案1】:

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

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

默认超时通常不够长,因此您可以将其增加到 10 分钟,这通常在 Dynamo 支持的情况下可以解决问题。

只有当索引处于 REGISTERED 状态时,您才能执行重新索引。重新索引完成后,您需要等到它启用。通过重用上面的代码示例并将状态更改为 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

【讨论】:

  • 感谢您的回复。这将返回关于ChronoUnit 的错误:No such property: ChronoUnit for class: groovysh_evaluate
  • 使用 Gremlin 控制台时必须导入该类。我为你更新了答案。
  • 添加该步骤会生成java.lang.NullPointerException。我已编辑问题以包含我粘贴到 Gremlin 中的确切命令。
  • 谢谢,但不幸的是它不起作用。错误:No signature of method: groovysh_evaluate.getOrCreateIfNotExist()。我将一个字符串(属性名称)作为第二个参数传递,因为 propertyKeyName 没有在任何地方定义。我在 Titan API 文档中找不到这个函数。这在 Gremlin shell 中是否适合您?
  • 请记住,这是 Java 代码,您可能需要对其稍作更改以使其在 Gremlin 控制台中运行;)
【解决方案2】:

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

此外,围绕事务管理还有各种微妙之处,以及在什么情况下事务将保持打开状态;我相信 Titan 1.0.0 在这方面没有来自 TinkerPop 的最新版本。您是否尝试过在启动后立即创建索引?

最后,索引创建过程会根据被索引的属性键之前是否使用过而有所不同。您是在尝试索引新键还是现有键?

【讨论】:

  • 我在单个 AWS t2.micro 实例 (Linux) 上运行单个实例。是的,我尝试重新启动服务器并立即创建索引,但没有成功。我尝试使用一些使用属性键的现有顶点进行索引。我还删除了所有顶点并尝试创建索引。我每次都得到相同的结果。
  • 对于它的价值,删除所有顶点不会影响重新索引的需要 - 根据属性键是否在模式中进行确定,而 Titan 中的模式是不可变的。我肯定会尝试通过在您以前从未使用过的属性键上创建索引来重现(当然,您必须在与索引相同的管理事务中创建它们)。
  • 尝试了您的建议,但它也失败了。我尝试在同一事务中创建一个全新的属性键和该道具键的索引。请参阅我的编辑 2。
  • OK 这确实有效。我有一个工作索引!那么为什么我不能在现有的属性键上创建索引呢?编辑 2 已更新。
  • 您应该能够在现有属性键上创建索引,但正如另一个答案提到的,您需要在索引可用之前启动重新索引。但是,如果您仍然看到过时的交易警报,我会首先尝试追踪这些警报。我不相信陈旧的事务清理逻辑会使索引“可重新索引”。
猜你喜欢
  • 2013-02-01
  • 2019-04-16
  • 2019-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多