Cassandra TOKEN分页机制出现问题

时间:2019-07-08 19:18:12

标签: java cassandra

我们的数据集有很多重复的分区键。我们正在使用TOKEN方法对数据进行分页。如果将具有重复键的行分散在一个页面上,则在下一次调用时我们不会得到其余重复项。

例如,假设我们具有以下键:1 2 3 5 5 5 6 7 8,每个查询限制为5行。第一个查询“ 从表中的TOKEN(id)> TOKEN('')限制5; 中选择*”按预期返回1 2 3 5 5。第二个查询“ 从表中的TOKEN(id)> TOKEN('5')限制5; 中选择*”返回6 78。这不是期望的行为,我们希望第二个查询返回5 6 7 8.考虑到这一点,很明显会发生这种情况:如果id == 5

,“ (TOKEN(id)> TOKEN('5')”)失败。

我们是在做错什么,还是这只是它的工作方式?我们正在使用最新的Java驱动程序,但是我认为这不是驱动程序问题,因为Golang驱动程序也表现出这种行为

(大多数)我们通过在行集的末尾删除任何重复的记录(示例中的5 5)或删除最后一条记录(以覆盖最后一条记录被重复的情况)来解决该问题。在第二个记录集中)。如果记录集是所有重复项,则此操作将失败。显然,更大的限制会减少这种情况,但是在生产环境中使用它似乎并不安全。

*已编辑*

在很多页面上,无论是Stackoverflow上还是Web上的其他地方,都建议使用TOKEN方法。但显然它不起作用:-(

@alex:

感谢您的回复。例子就是这个问题的简化例子。实际上,我们有3000万行,限制使用的行数为1000。几年前首次设计表格时,设计人员不了解分区键的工作原理,因此他们使用用户ID作为分区,因此给我们提供了3000万个分区。我们认为,这至少有助于我们的快速修复时间(当前群集的修复时间为12小时)。我们需要将整个表复制到具有不同分区键的新表中(在实时生产环境中),以解决分区键问题。 https://docs.datastax.com/en/developer/java-driver/2.1/manual/paging/页似乎是一个更好的解决方案。

@Nadav:

感谢您的回复。仅仅删除限制将导致请求在我们软件的多层超时。上面的DataStax页面似乎是我们的最佳解决方案。

2 个答案:

答案 0 :(得分:1)

您正在混淆几件事-在Cassandra中,数据是在分区内组织的,您可以通过分区键获取数据,或使用token函数执行范围扫描。查询的结果可以通过pages传递给应用程序-您可以指定获取大小(尽管5很小),获取一页,处理,下一步,...等直到结果集筋疲力尽。

在您的情况下,页面大小与结果集大小不匹配-那里有6个结果,而下一个结果集(对于token(id) > token(5))只有3行。我不知道一个开箱即用的解决方案(select * from table除外,但是如果您有很多数据,它可能会超时)。在您的情况下,我最好使用更大的范围(例如,整个令牌范围),并在其中使用页面结果(不使用limit),然后在需要切换到下一个令牌范围时进行处理,并且您还有一些先前令牌范围内剩余的行。

我有一个example of Java code,正在对所有令牌范围进行有效扫描,类似于Spark连接器所做的事情。那里的主要技巧是将请求路由到保存数据的节点,因此它将直接从节点本身读取数据,而无需到达其他节点(当然,如果您正在使用LOCAL_ONE进行读取)。

答案 1 :(得分:1)

您不应该也不能使用令牌范围和LIMIT来翻页结果,您发现自己不起作用-因为LIMIT会截断某些结果,因此您无法继续。

相反,Cassandra为您提供了一个单独的分页功能:您发出请求,获取前1000行(或任意行),并使用“ cookie”可以继续查询以获取下一页结果。请以您喜欢的语言使用Cassandra paging 的语法,请参阅您喜欢的驱动程序的文档。不是“ LIMIT”-这是一项单独的功能。

将大型查询拆分为多个令牌范围仍然有其用途。例如,它允许您在 parallel 中查询不同的范围,因为不同的令牌范围通常来自不同的节点。但是,您仍然需要使用分页来查询每个范围以完成操作,并且不能使用“ LIMIT”,因为您不知道每个范围期望多少结果,并且需要全部读取。