2

我使用 Apache Spark 从 Cassandra 读取数据,这在后台是基于令牌范围的扫描。但是,最近我在从我的 Cassandra 表中读取数据时看到了很多失败。

读取失败,原因如下:

Caused by: com.datastax.driver.core.exceptions.ReadFailureException: Cassandra failure during read query at consistency LOCAL_ONE (1 responses were required but only 0 replica responded, 1 failed)    
at com.datastax.driver.core.exceptions.ReadFailureException.copy(ReadFailureException.java:85)  
at com.datastax.driver.core.exceptions.ReadFailureException.copy(ReadFailureException.java:27)  
at com.datastax.driver.core.DriverThrowables.propagateCause(DriverThrowables.java:37)   
at com.datastax.driver.core.DefaultResultSetFuture.getUninterruptibly(DefaultResultSetFuture.java:245)  
at com.datastax.driver.core.AbstractSession.execute(AbstractSession.java:68)

当我检查系统日志时,我发现了以下问题:

ERROR [ReadStage-1] 2020-04-09 10:25:59,701 StorageProxy.java:1896 - Scanned over 100001 tombstones during query 'SELECT * FROM my_keyspace.my_table WHERE token(id) > -5868586221781016365 AND token(id) <= -5347313590141106513 LIMIT 5000' (last scanned row partion key was (my_key_1)); query aborted

错误日志是直截了当的,由于墓碑扫描,读取失败。

我没有得到的是,我运行同一个 Spark 工作一年多了,从来没有遇到过这个问题。但是,那是次要的。首先我想知道我该如何解决这个问题?

可以为未传递的列值创建墓碑,因为我使用 Cassandra Insert Json 功能插入文档。在这里确认,这种方法将创建墓碑。

我该如何解决?基于非空值创建多个插入查询是一个复杂的选项。

在我看来,即使插入虚拟值也是不切实际的。从这些表中读取数据的所有客户端都需要进行更改。

如果 JSON 中不存在列,我个人认为 Cassandra 永远不应该为列创建 Tombstone。

解决此问题的其他选择是什么?

4

1 回答 1

2

你有几种可能性:

  1. 不要将数据作为 JSON 插入,而是在应用程序中解析 JSON,并插入数据,使用unset而不是缺失值(默认完成,查看文档) - 您可以通过将 JSON 映射到 POJO 并使用 Object Mapper 来简化工作还支持用unset. 这是最好的方法,因为墓碑会影响所有应用程序以及 Cassandra 本身。但真正的解决方案将取决于您的用例——您是仅插入新数据,还是同时更新现有数据?在后一种情况下,您需要确保覆盖以前的数据
  2. 减小 Spark 应用程序中的页面大小以在一页中读取更少的行。这由docs 中描述spark.cassandra.input.fetch.size_in_rows的参数调节。如果您将 DSE 与 DSE Analytics 一起使用,您可能需要禁用连续分页
于 2020-05-13T14:18:13.520 回答