2016-01-09 12 views
16

Ho un client Java che spinge (INSERIRE) i record in batch sul cluster Cassandra. Gli elementi nel batch hanno tutti la stessa chiave di riga, quindi saranno tutti posizionati nello stesso nodo. Inoltre non ho bisogno che la transazione sia atomica, quindi ho usato batch non loggato.Qual è il limite di batch in Cassandra?

Il numero di comandi INSERT in ogni batch dipende da diversi fattori, ma può essere compreso tra 5 e 50000. Prima ho inserito tutti i comandi che avevo in un batch e l'ho inviato. Questo ha gettato com.datastax.driver.core.exceptions.InvalidQueryException: Batch too large. Poi ho usato un tappo di 1000 INSERT per batch e poi giù a 300. Ho notato che sto solo indovinando casualmente senza sapere esattamente da dove viene questo limite, che può causare problemi lungo la strada.

La mia domanda è, qual è questo limite? Posso modificarlo? Come posso sapere quanti elementi possono essere inseriti in un lotto? Quando il mio batch è "pieno"?

risposta

17

Suggerirei di non aumentare il limite e di suddividerlo in più richieste. Mettere tutto in una singola richiesta gigante avrà un impatto negativo sul coordinatore in modo significativo. Avere tutto in una partizione può migliorare il throughput in alcuni batch di dimensioni riducendo la latenza, ma i batch non sono mai pensati per essere utilizzati per migliorare le prestazioni. Quindi, tentare di ottimizzare per ottenere il massimo throughput utilizzando dimensioni di batch diverse dipenderà in gran parte dal caso d'uso/schema/nodi e richiederà test specifici, poiché generalmente c'è un picco nelle dimensioni in cui inizia a degradarsi.

c'è un'opzione

# Fail any batch exceeding this value. 50kb (10x warn threshold) by default. 
batch_size_fail_threshold_in_kb: 50 

nel vostro cassandra.yaml per aumentarlo, ma essere sicuri di test per assicurarsi che il vostro in realtà aiutare e non ferire sei il throughput.

+0

Questo è quello che stavo cercando, grazie. Sai qual è il modo migliore per monitorare le dimensioni del batch nel client? –

+2

Dipende dal driver che si sta utilizzando, ma nel driver java è possibile utilizzare getValues ​​() su ogni singola istruzione nel batch che restituisce una matrice di ByteBuffers per cui è possibile utilizzare il metodo rimanente() per ottenere la dimensione di i buffer individualmente e li sommano tutti, ma in generale non consiglierei di farlo. Non dovresti creare lotti super grandi, ma abbastanza grandi da farti sentire che non sei neanche lontanamente vicino a quel limite. –

+0

bene ci sono un sacco di cose qui. C * predica il design per colonna invece di righe e C * dice colonne 2B per partizione ma sappiamo empiricamente che il punto ottimale è 100 MB.quindi anche con una partizione da 100 MB e se la dimensione predefinita di un batch è 50 KB che è come 100 MB/50 KB = 3125 richieste per recuperare una partizione da 100 MB in modo da troppe richieste. – user1870400

2

Guardando la Cassandra registra sarete in grado di individuare le cose come:

ERRORE 19:54:13 Batch per [risultati] è di dimensione 103.072 KiB, superando la soglia specificata di 50.000 KiB per 53.072 KiB. (Vedi batch_size_fail_threshold_in_kb)

0

imbattuto in un problema simile in Java, ecco un esempio funzionale di come lotti lotti:

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 variabile sarà necessario modificare in base alle dimensioni dei singoli record di essere inserito.

Problemi correlati