Как избежать сбоя чтения Кассандры из-за больших сканированных надгробий?

Я использую 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 для вставки документа. Подтверждено здесь, что этот подход создаст надгробия.

Как я могу это исправить? Создание нескольких запросов на вставку на основе ненулевых значений - сложный вариант.

На мой взгляд, даже вставка фиктивного значения непрактична. Все клиенты, которые читают данные из этих таблиц, должны внести изменения.

Я лично считаю, что Cassandra никогда не должна создавать Tombstone для столбца, если столбец не существует в JSON.

Какие еще варианты решения этой проблемы?


person Bikas Katwal    schedule 13.05.2020    source источник
comment
У этих сбоев может быть несколько причин. Какие запросы вы пытаетесь выполнить? Вы пытаетесь извлечь все записи из таблицы без ключа?   -  person user1401472    schedule 13.05.2020
comment
Я знаю, что это не помогает, но самый простой способ уменьшить количество надгробий в Cassandra - это создать модели данных, которые вообще не создают их. Я бы хотел, чтобы больше людей поняли это.   -  person Aaron    schedule 13.05.2020
comment
@Aaron Согласитесь, это не помогает :) Не всегда удается избежать надгробий. Но есть способы решить или минимизировать проблему, у меня было несколько вариантов, но в настоящий момент они невозможны. Итак, задавал вопросы. Я знаю, что есть способы избежать надгробий на основе столбцов, сохранив мои данные в Map или text типе и сохранив JSON. Нам нужна схема. Не стесняйтесь предложить, думали ли вы о какой-либо другой модели данных, чтобы избежать надгробий? Спасибо!! :)   -  person Bikas Katwal    schedule 13.05.2020


Ответы (1)


У вас есть несколько возможностей:

  1. Не вставляйте данные в формате JSON, а вместо этого анализируйте JSON в приложении и вставляйте данные, используя unset вместо отсутствующих значений (выполняется по умолчанию, см. документацию) - вы можете упростить свою работу, сопоставив JSON с POJO и используя Object Mapper, который также поддерживает замену нулей на unset. Это лучший подход, так как надгробия повлияют на все приложения и саму Cassandra. Но реальное решение будет зависеть от вашего варианта использования - вставляете ли вы только новые данные или обновляете уже существующие? В последнем случае вам нужно будет убедиться, что вы перезаписали предыдущие данные.
  2. Уменьшите размер страницы в приложении Spark, чтобы читать меньше строк на одной странице. Это регулируется параметром spark.cassandra.input.fetch.size_in_rows, описано в документации. Если вы используете DSE с DSE Analytics, вам может потребоваться отключить непрерывное разбиение на страницы.
person Alex Ott    schedule 13.05.2020
comment
Спасибо, Алекс. На данный момент мы только вставляем, это может быть новая запись или запись с тем же ключом, который существует в нашей таблице. Вставить и вставить - person Bikas Katwal; 13.05.2020
comment
Спасибо именно то, что я искал. Я выберу второй вариант и посмотрю, как он работает. В конечном итоге нам определенно нужно изменить наш код, чтобы принять первый вариант. - person Bikas Katwal; 13.05.2020
comment
для upsert может возникнуть проблема со следующим - например, первая вставка была с полями 1 и 3, а вторая - с полями 1,4,5 - если вы не поместите null для поля 3, вы закончите с поля 1,3,4,5, а это не всегда нужно. Надгробия при вставке JSON предназначены специально для предотвращения таких случаев. - person Alex Ott; 13.05.2020
comment
Как вы упомянули о unest. Я проверял ту же функцию в Insert Json. docs.datastax.com/en/dse/5.1/ cql / cql / cql_using / Я предполагаю, что это имеет тот же эффект. Из документа Use the DEFAULT UNSET option to only overwrite values found in the JSON string - person Bikas Katwal; 13.05.2020
comment
Мы довольно часто используем upserts, так как в нашем потоке NRT приходит много документов с одним и тем же ключом раздела. Так что надгробий избежать не удастся. Я выбираю меньший размер выборки. Посмотри, как получится. - person Bikas Katwal; 13.05.2020
comment
Да, unset по умолчанию может вам помочь (я всегда забываю об этом, поскольку я редко вижу JSON в дикой природе), но будет такая же проблема со слиянием с предыдущими данными ... - person Alex Ott; 13.05.2020