Каков предел в Кассандре?
У меня есть клиент Java, который толкает (INSERT) записи в пакетном режиме в кластер Cassandra. Элементы в пакете имеют один и тот же ключ строки, поэтому все они будут помещены в один и тот же node. Также мне не нужно, чтобы транзакция была атомарной, поэтому я использую пакет с немаркированной версией.
Количество команд INSERT в каждой партии зависит от разных факторов, но может быть от 5 до 50000. Сначала я просто поставил столько команд, сколько было в одной партии, и отправил их. Это бросило com.datastax.driver.core.exceptions.InvalidQueryException: Batch too large
. Затем я использовал кепку 1000 INSERT за партию, а затем до 300. Я заметил, что я просто случайно догадываюсь, не зная точно, откуда этот предел, что может вызвать проблемы на дороге.
Мой вопрос: что это за предел? Могу ли я изменить его? Как узнать, сколько элементов можно поместить в пакет? Когда моя партия "заполнена"?
Ответы
Ответ 1
Я бы порекомендовал не увеличивать ограничение, а просто разбивать на несколько запросов. Помещение всего в один гигантский запрос значительно отрицательно повлияет на координатора. Наличие всего в одном разделе может улучшить пропускную способность в пакетах некоторых размеров за счет уменьшения некоторой задержки, но пакеты никогда не предназначены для повышения производительности. Таким образом, попытка оптимизации для получения максимальной пропускной способности с использованием разных размеров пакетов будет зависеть в значительной степени от варианта использования/схемы/узлов и потребует специального тестирования, поскольку обычно существует ограничение на размер, где он начинает ухудшаться.
Eсть
# Fail any batch exceeding this value. 50kb (10x warn threshold) by default.
batch_size_fail_threshold_in_kb: 50
вариант в вашем cassandra.yaml
чтобы увеличить его, но не забудьте проверить, чтобы убедиться, что вы действительно помогаете, а не снижаете пропускную способность.
Ответ 2
Посмотрев на журналы Cassandra, вы сможете увидеть такие вещи, как:
ОШИБКА 19:54:13 Партия для [матчей] имеет размер 103.072KiB, превышающий заданный порог 50.000KiB на 53.072KiB. (см. batch_size_fail_threshold_in_kb)
Ответ 3
Я исправил эту проблему, изменив CHUNKSIZE на более низкое значение (например, 1)
https://docs.datastax.com/en/cql/3.1/cql/cql_reference/copy_r.html
COPY mytable FROM 'mybackup' С CHUNKSIZE = 1;
Операция выполняется намного медленнее, но по крайней мере она работает сейчас
Ответ 4
Перейдите по аналогичной проблеме на Java, вот функциональный пример того, как пакетные партии:
import com.datastax.driver.core.BatchStatement;
import com.datastax.driver.core.PreparedStatement;
import com.datastax.driver.core.Session;
import com.google.common.collect.Lists;
import java.util.Collection;
import java.util.stream.Collectors;
public class CassandraBatchOfBatchesExample {
private final PreparedStatement statement;
private final Session session;
private final int batchSize;
public CassandraBatchOfBatchesExample(Session session, int batchSize) {
this.session = session;
this.batchSize = batchSize;
statement = session.prepare("INSERT_INTO some_table JSON ?");
}
public void execute(Collection<String> jsons) {
Lists.partition(jsons
.stream()
.map(statement::bind)
.collect(Collectors.toList()
), batchSize).stream()
.map(statements -> new BatchStatement().addAll(statements))
.forEach(session::execute);
}
}
batchSize
переменная должна измениться в зависимости от размера отдельных вставленных записей.