Bătălia celor doi yakozuna, sau Cassandra vs HBase. Experiența echipei Sberbank

Aceasta nu este nici măcar o glumă, se pare că această imagine reflectă cel mai exact esența acestor baze de date și, în cele din urmă, va fi clar de ce:

Bătălia celor doi yakozuna, sau Cassandra vs HBase. Experiența echipei Sberbank

Conform DB-Engines Ranking, cele mai populare două baze de date columnare NoSQL sunt Cassandra (denumită în continuare CS) și HBase (HB).

Bătălia celor doi yakozuna, sau Cassandra vs HBase. Experiența echipei Sberbank

Prin voința sorții, echipa noastră de gestionare a încărcării datelor de la Sberbank a făcut-o deja demult și lucrează îndeaproape cu HB. În acest timp, i-am studiat destul de bine punctele tari și punctele slabe și am învățat cum să-l gătim. Totuși, prezența unei alternative sub formă de CS ne-a obligat mereu să ne chinuim puțin cu îndoieli: am făcut alegerea corectă? Mai mult, rezultatele comparații, realizat de DataStax, ei au spus că CS îl învinge cu ușurință pe HB cu aproape un scor zdrobitor. Pe de altă parte, DataStax este o parte interesată și nu ar trebui să le credeți pe cuvânt. Am fost derutați și de cantitatea destul de mică de informații despre condițiile de testare, așa că am decis să aflăm singuri cine este regele BigData NoSql, iar rezultatele obținute s-au dovedit a fi foarte interesante.

Cu toate acestea, înainte de a trece la rezultatele testelor efectuate, este necesar să descriem aspectele semnificative ale configurațiilor mediului. Faptul este că CS poate fi folosit într-un mod care permite pierderea datelor. Acestea. acest lucru este atunci când un singur server (nod) este responsabil pentru datele unei anumite chei, iar dacă din anumite motive eșuează, atunci valoarea acestei chei se va pierde. Pentru multe sarcini acest lucru nu este critic, dar pentru sectorul bancar aceasta este mai degrabă excepția decât regula. În cazul nostru, este important să avem mai multe copii ale datelor pentru o stocare fiabilă.

Prin urmare, a fost luat în considerare doar modul de operare CS în modul de replicare triplă, adică. Crearea casespace a fost realizată cu următorii parametri:

CREATE KEYSPACE ks WITH REPLICATION = {'class' : 'NetworkTopologyStrategy', 'datacenter1' : 3};

În continuare, există două moduri de a asigura nivelul necesar de consistență. Regula generala:
NV + NR > RF

Ceea ce înseamnă că numărul de confirmări de la noduri la scriere (NW) plus numărul de confirmări de la noduri la citire (NR) trebuie să fie mai mare decât factorul de replicare. În cazul nostru, RF = 3, ceea ce înseamnă că următoarele opțiuni sunt potrivite:
2 + 2 > 3
3 + 1 > 3

Deoarece este fundamental pentru noi să stocăm datele cât mai fiabil posibil, a fost aleasă schema 3+1. În plus, HB funcționează pe un principiu similar, adică. o astfel de comparație va fi mai corectă.

Trebuie remarcat faptul că DataStax a făcut opusul în studiul lor, au stabilit RF = 1 atât pentru CS, cât și pentru HB (pentru acesta din urmă prin modificarea setărilor HDFS). Acesta este un aspect cu adevărat important, deoarece impactul asupra performanței CS în acest caz este uriaș. De exemplu, imaginea de mai jos arată creșterea timpului necesar pentru încărcarea datelor în CS:

Bătălia celor doi yakozuna, sau Cassandra vs HBase. Experiența echipei Sberbank

Aici vedem următoarele: cu cât mai multe fire concurente scriu date, cu atât durează mai mult. Acest lucru este natural, dar este important ca degradarea performanței pentru RF=3 să fie semnificativ mai mare. Cu alte cuvinte, dacă scriem 4 fire în 5 tabele fiecare (20 în total), atunci RF=3 pierde de aproximativ 2 ori (150 de secunde pentru RF=3 față de 75 pentru RF=1). Dar dacă creștem încărcarea prin încărcarea datelor în 8 tabele cu 5 fire fiecare (40 în total), atunci pierderea RF=3 este deja de 2,7 ori (375 secunde față de 138).

Poate că acesta este parțial secretul testării de încărcare cu succes efectuate de DataStax pentru CS, deoarece pentru HB la standul nostru schimbarea factorului de replicare de la 2 la 3 nu a avut niciun efect. Acestea. discurile nu sunt blocajul HB pentru configurația noastră. Cu toate acestea, există multe alte capcane aici, pentru că trebuie remarcat faptul că versiunea noastră de HB a fost ușor reparată și ajustată, mediile sunt complet diferite etc. De asemenea, merită remarcat faptul că poate pur și simplu nu știu cum să pregătesc corect CS și există câteva modalități mai eficiente de a lucra cu el și sper că vom afla în comentarii. Dar mai întâi lucrurile.

Toate testele au fost efectuate pe un cluster hardware format din 4 servere, fiecare cu următoarea configurație:

CPU: Xeon E5-2680 v4 @ 2.40GHz 64 fire.
Discuri: 12 bucăți HDD SATA
versiunea java: 1.8.0_111

Versiunea CS: 3.11.5

parametrii cassandra.ymlnum_tokens: 256
hinted_handoff_enabled: adevărat
hinted_handoff_throttle_in_kb: 1024
max_hints_delivery_threads: 2
directorul_hints: /data10/cassandra/hints
hints_flush_period_in_ms: 10000
max_hints_file_size_in_mb: 128
batchlog_replay_throttle_in_kb: 1024
autentificator: AllowAllAuthenticator
autorizator: AllowAllAuthorizer
role_manager: CassandraRoleManager
validitatea_rolurilor_în_ms: 2000
permissions_validity_in_ms: 2000
credentials_validity_in_ms: 2000
partitioner: org.apache.cassandra.dht.Murmur3Partitioner
directoare_fișier_date:
- /data1/cassandra/data # fiecare director dataN este un disc separat
- /data2/cassandra/data
- /data3/cassandra/data
- /data4/cassandra/data
- /data5/cassandra/data
- /data6/cassandra/data
- /data7/cassandra/data
- /data8/cassandra/data
directorul_commitlog: /data9/cassandra/commitlog
cdc_enabled: false
disk_failure_policy: opriți
commit_failure_policy: opriți
prepared_statements_cache_size_mb:
thrift_prepared_statements_cache_size_mb:
key_cache_size_in_mb:
key_cache_save_period: 14400
row_cache_size_in_mb: 0
row_cache_save_period: 0
counter_cache_size_in_mb:
counter_cache_save_period: 7200
directorul_caches_salvate: /data10/cassandra/saved_caches
commitlog_sync: periodic
commitlog_sync_period_in_ms: 10000
commitlog_segment_size_in_mb: 32
seed_provider:
- class_name: org.apache.cassandra.locator.SimpleSeedProvider
parametri:
— semințe: „*,*”
concurrent_reads: 256 # încercat 64 - nu s-a observat nicio diferență
concurrent_writes: 256 # tried 64 - nicio diferență observată
concurrent_counter_writes: 256 # încercat 64 - nu s-a observat nicio diferență
concurrent_materialized_view_writes: 32
memtable_heap_space_in_mb: 2048 # încercat 16 GB - a fost mai lent
memtable_allocation_type: heap_buffers
index_summary_capacity_in_mb:
index_summary_resize_interval_in_minutes: 60
trickle_fsync: fals
trickle_fsync_interval_in_kb: 10240
port_stocare: 7000
ssl_storage_port: 7001
listen_dress: *
adresa_difuzare: *
listen_on_broadcast_address: adevărat
internode_authenticator: org.apache.cassandra.auth.AllowAllInternodeAuthenticator
start_native_transport: adevărat
port_nativ_de_transport: 9042
start_rpc: adevărat
adresa_rpc: *
rpc_port: 9160
rpc_keepalive: adevărat
rpc_server_type: sincronizare
thrift_framed_transport_size_in_mb: 15
incremental_backups: false
snapshot_before_compaction: false
auto_snapshot: adevărat
dimensiunea_indexului_coloanelor_în_kb: 64
column_index_cache_size_in_kb: 2
compactoare_concurente: 4
compaction_throughput_mb_per_sec: 1600
sstable_preemptive_open_interval_in_mb: 50
read_request_timeout_in_ms: 100000
range_request_timeout_in_ms: 200000
write_request_timeout_in_ms: 40000
counter_write_request_timeout_in_ms: 100000
cas_contention_timeout_in_ms: 20000
truncate_request_timeout_in_ms: 60000
request_timeout_in_ms: 200000
slow_query_log_timeout_in_ms: 500
cross_node_timeout: fals
endpoint_snitch: GossipingPropertyFileSnitch
dynamic_snitch_update_interval_in_ms: 100
dynamic_snitch_reset_interval_in_ms: 600000
dynamic_snitch_badness_threshold: 0.1
request_scheduler: org.apache.cassandra.scheduler.NoScheduler
server_encryption_options:
internode_encryption: niciunul
client_encryption_options:
activat: false
compresie_internod: dc
inter_dc_tcp_nodelay: fals
tracetype_query_ttl: 86400
tracetype_repair_ttl: 604800
enable_user_defined_functions: false
enable_scripted_user_defined_functions: false
windows_timer_interval: 1
transparent_data_encryption_options:
activat: false
tombstone_warn_threshold: 1000
tombstone_failure_threshold: 100000
batch_size_warn_threshold_in_kb: 200
batch_size_fail_threshold_in_kb: 250
unlogged_batch_across_partitions_warn_threshold: 10
compaction_large_partition_warning_threshold_mb: 100
gc_warn_threshold_in_ms: 1000
back_pressure_enabled: fals
enable_materialized_views: adevărat
enable_sasi_indexes: adevărat

Setări GC:

### Setări CMS-XX:+UtilizațiParNewGC
-XX:+UtilizațiConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=1
-XX:CMSInitiatingOccupancyFraction=75
-XX:+Utilizați CMSIInitiating OccupancyOnly
-XX:CMSWaitDuration=10000
-XX:+CMSParallelInitialMarkEnabled
-XX:+CMSEdenChunksRecordAlways
-XX:+CMSClassUnloadingEnabled

Memoria jvm.options i s-a alocat 16Gb (am încercat și 32 Gb, nu s-a observat nicio diferență).

Tabelele au fost create cu comanda:

CREATE TABLE ks.t1 (id bigint PRIMARY KEY, title text) WITH compression = {'sstable_compression': 'LZ4Compressor', 'chunk_length_kb': 64};

Versiunea HB: 1.2.0-cdh5.14.2 (în clasa org.apache.hadoop.hbase.regionserver.HRegion am exclus MetricsRegion, ceea ce a condus la GC când numărul de regiuni a fost mai mare de 1000 pe RegionServer)

Parametrii HBase care nu sunt implicitizookeeper.session.timeout: 120000
hbase.rpc.timeout: 2 minute(e)
hbase.client.scanner.timeout.period: 2 minute(e)
hbase.master.handler.count: 10
hbase.regionserver.lease.period, hbase.client.scanner.timeout.period: 2 minut(e)
hbase.regionserver.handler.count: 160
hbase.regionserver.metahandler.count: 30
hbase.regionserver.logroll.period: 4 ore(e)
hbase.regionserver.maxlogs: 200
hbase.hregion.memstore.flush.size: 1 GiB
hbase.hregion.memstore.block.multiplicator: 6
hbase.hstore.compactionThreshold: 5
hbase.hstore.blockingStoreFiles: 200
hbase.hregion.majorcompaction: 1 zi(le)
Fragment de configurare avansată a serviciului HBase (supapă de siguranță) pentru hbase-site.xml:
hbase.regionserver.wal.codecorg.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec
hbase.master.namespace.init.timeout3600000
hbase.regionserver.optionalcacheflushinterval18000000
hbase.regionserver.thread.compaction.large12
hbase.regionserver.wal.enablecompressiontrue
hbase.hstore.compaction.max.size1073741824
hbase.server.compactchecker.interval.multiplier200
Opțiuni de configurare Java pentru HBase RegionServer:
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:ReservedCodeCacheSize=256m
hbase.snapshot.master.timeoutMillis: 2 minut(e)
hbase.snapshot.region.timeout: 2 minute(e)
hbase.snapshot.master.timeout.millis: 2 minut(e)
Dimensiunea maximă a jurnalului serverului REST HBase: 100 MiB
Copii de rezervă maxime ale fișierelor jurnal ale serverului HBase REST: 5
Dimensiunea maximă a jurnalului de server HBase Thrift: 100 MiB
Numărul maxim de copii de rezervă ale fișierelor jurnal HBase Thrift Server: 5
Dimensiunea maximă a jurnalului principal: 100 MiB
Copii de rezervă maxime master ale fișierelor jurnal: 5
Dimensiunea maximă a jurnalului RegionServer: 100 MiB
Copii de rezervă maxime ale fișierelor jurnal RegionServer: 5
Fereastra de detectare a masterului activ HBase: 4 minute(e)
dfs.client.hedged.read.threadpool.dimensiune: 40
dfs.client.hedged.read.threshold.millis: 10 milisecunde(e)
hbase.rest.threads.min: 8
hbase.rest.threads.max: 150
Descriptori maxim de fișiere de proces: 180000
hbase.thrift.minWorkerThreads: 200
hbase.master.executor.openregion.threads: 30
hbase.master.executor.closeregion.threads: 30
hbase.master.executor.serverops.threads: 60
hbase.regionserver.thread.compaction.small: 6
Dimensiune.hbase.ipc.server.read.threadpool: 20
Subiecte pentru mutarea regiunii: 6
Dimensiunea heap client Java în octeți: 1 GiB
HBase REST Server Grup implicit: 3 GiB
Grup implicit de server HBase Thrift: 3 GiB
Dimensiunea heap Java a HBase Master în octeți: 16 GiB
Dimensiunea heap Java a HBase RegionServer în octeți: 32 GiB

+ ZooKeeper
maxClientCnxns: 601
maxSessionTimeout: 120000
Crearea tabelelor:
hbase org.apache.hadoop.hbase.util.RegionSplitter ns:t1 UniformSplit -c 64 -f cf
modificați 'ns:t1', {NAME => 'cf', DATA_BLOCK_ENCODING => 'FAST_DIFF', COMPRESSION => 'GZ'}

Există un punct important aici - descrierea DataStax nu spune câte regiuni au fost utilizate pentru a crea tabelele HB, deși acest lucru este critic pentru volume mari. Prin urmare, pentru teste s-a ales cantitate = 64, ceea ce permite stocarea până la 640 GB, adică. masa de marime medie.

La momentul testării, HBase avea 22 de mii de tabele și 67 de mii de regiuni (acest lucru ar fi fost letal pentru versiunea 1.2.0 dacă nu pentru patch-ul menționat mai sus).

Acum pentru cod. Deoarece nu era clar care configurații erau mai avantajoase pentru o anumită bază de date, testele au fost efectuate în diferite combinații. Acestea. în unele teste, s-au încărcat simultan 4 tabele (toate cele 4 noduri au fost folosite pentru conectare). În alte teste am lucrat cu 8 tabele diferite. În unele cazuri, dimensiunea lotului a fost 100, în altele 200 (parametrul lotului - vezi codul de mai jos). Dimensiunea datelor pentru valoare este de 10 octeți sau 100 de octeți (dataSize). În total, 5 milioane de înregistrări au fost scrise și citite în fiecare tabel de fiecare dată. În același timp, în fiecare tabel au fost scrise/citite 5 fire de execuție (numărul firului de execuție - thNum), fiecare dintre ele folosind propriul interval de chei (număr = 1 milion):

if (opType.equals("insert")) {
    for (Long key = count * thNum; key < count * (thNum + 1); key += 0) {
        StringBuilder sb = new StringBuilder("BEGIN BATCH ");
        for (int i = 0; i < batch; i++) {
            String value = RandomStringUtils.random(dataSize, true, true);
            sb.append("INSERT INTO ")
                    .append(tableName)
                    .append("(id, title) ")
                    .append("VALUES (")
                    .append(key)
                    .append(", '")
                    .append(value)
                    .append("');");
            key++;
        }
        sb.append("APPLY BATCH;");
        final String query = sb.toString();
        session.execute(query);
    }
} else {
    for (Long key = count * thNum; key < count * (thNum + 1); key += 0) {
        StringBuilder sb = new StringBuilder("SELECT * FROM ").append(tableName).append(" WHERE id IN (");
        for (int i = 0; i < batch; i++) {
            sb = sb.append(key);
            if (i+1 < batch)
                sb.append(",");
            key++;
        }
        sb = sb.append(");");
        final String query = sb.toString();
        ResultSet rs = session.execute(query);
    }
}

În consecință, au fost furnizate funcționalități similare pentru HB:

Configuration conf = getConf();
HTable table = new HTable(conf, keyspace + ":" + tableName);
table.setAutoFlush(false, false);
List<Get> lGet = new ArrayList<>();
List<Put> lPut = new ArrayList<>();
byte[] cf = Bytes.toBytes("cf");
byte[] qf = Bytes.toBytes("value");
if (opType.equals("insert")) {
    for (Long key = count * thNum; key < count * (thNum + 1); key += 0) {
        lPut.clear();
        for (int i = 0; i < batch; i++) {
            Put p = new Put(makeHbaseRowKey(key));
            String value = RandomStringUtils.random(dataSize, true, true);
            p.addColumn(cf, qf, value.getBytes());
            lPut.add(p);
            key++;
        }
        table.put(lPut);
        table.flushCommits();
    }
} else {
    for (Long key = count * thNum; key < count * (thNum + 1); key += 0) {
        lGet.clear();
        for (int i = 0; i < batch; i++) {
            Get g = new Get(makeHbaseRowKey(key));
            lGet.add(g);
            key++;
        }
        Result[] rs = table.get(lGet);
    }
}

Întrucât în ​​HB clientul trebuie să aibă grijă de distribuirea uniformă a datelor, funcția cheie de sare arăta astfel:

public static byte[] makeHbaseRowKey(long key) {
    byte[] nonSaltedRowKey = Bytes.toBytes(key);
    CRC32 crc32 = new CRC32();
    crc32.update(nonSaltedRowKey);
    long crc32Value = crc32.getValue();
    byte[] salt = Arrays.copyOfRange(Bytes.toBytes(crc32Value), 5, 7);
    return ArrayUtils.addAll(salt, nonSaltedRowKey);
}

Acum partea cea mai interesantă - rezultatele:

Bătălia celor doi yakozuna, sau Cassandra vs HBase. Experiența echipei Sberbank

Același lucru sub formă de grafic:

Bătălia celor doi yakozuna, sau Cassandra vs HBase. Experiența echipei Sberbank

Avantajul HB este atât de surprinzător încât există suspiciunea că există un fel de blocaj în configurarea CS. Cu toate acestea, căutarea pe Google și a celor mai evidenti parametri (cum ar fi concurrent_writes sau memtable_heap_space_in_mb) nu a accelerat lucrurile. În același timp, buștenii sunt curați și nu înjură nimic.

Datele au fost distribuite uniform între noduri, statisticile de la toate nodurile au fost aproximativ aceleași.

Așa arată statisticile tabelului de la unul dintre noduriSpațiu de taste: ks
Număr de citiri: 9383707
Latență de citire: 0.04287025042448576 ms
Număr de scrieri: 15462012
Latența de scriere: 0.1350068438699957 ms
Flushuri în așteptare: 0
Tabel: t1
Număr SSTable: 16
Spațiu folosit (live): 148.59 MiB
Spațiu utilizat (total): 148.59 MiB
Spațiu utilizat de instantanee (total): 0 octeți
Memorie off heap utilizată (total): 5.17 MiB
Raport de compresie SSTtable: 0.5720989576459437
Număr de partiții (estimare): 3970323
Număr de celule memorabile: 0
Dimensiunea datelor memorabile: 0 octeți
Memoria memorabilă din heap utilizată: 0 octeți
Număr de comutatoare memorabile: 5
Număr de citiri locale: 2346045
Latența de citire locală: NaN ms
Număr local de scrieri: 3865503
Latența de scriere locală: NaN ms
Fluxuri în așteptare: 0
Procent reparat: 0.0
Filtru Bloom false pozitive: 25
Raportul fals al filtrului Bloom: 0.00000
Spațiu utilizat pentru filtrul Bloom: 4.57 MiB
Filtrul Bloom din memoria heap utilizată: 4.57 MiB
Rezumatul indexului din memoria heap utilizată: 590.02 KiB
Metadatele de compresie din memoria heap utilizate: 19.45 KiB
Octeți minimi pentru partiția compactată: 36
Maximum de octeți pentru partiția compactată: 42
Octeți medii pentru partiția compactată: 42
Mediu celule vii pe felie (ultimele cinci minute): NaN
Celule vii maxime pe felie (ultimele cinci minute): 0
Pietre funerare medii pe felie (ultimele cinci minute): NaN
Pietre funerare maxime pe felie (ultimele cinci minute): 0
Mutații eliminate: 0 octeți

O încercare de a reduce dimensiunea lotului (chiar trimiterea lui individual) nu a avut niciun efect, doar s-a înrăutățit. Este posibil ca de fapt aceasta să fie într-adevăr performanța maximă pentru CS, deoarece rezultatele obținute pentru CS sunt similare cu cele obținute pentru DataStax - aproximativ sute de mii de operații pe secundă. În plus, dacă ne uităm la utilizarea resurselor, vom vedea că CS folosește mult mai mult CPU și discuri:

Bătălia celor doi yakozuna, sau Cassandra vs HBase. Experiența echipei Sberbank
Figura arată utilizarea în timpul rulării tuturor testelor la rând pentru ambele baze de date.

În ceea ce privește avantajul puternic de citire al lui HB. Aici puteți vedea că pentru ambele baze de date, utilizarea discului în timpul citirii este extrem de scăzută (testele de citire sunt partea finală a ciclului de testare pentru fiecare bază de date, de exemplu pentru CS, aceasta este de la 15:20 la 15:40). În cazul HB, motivul este clar - majoritatea datelor se blochează în memorie, în memstore, iar unele sunt stocate în cache în blockcache. În ceea ce privește CS, nu este foarte clar cum funcționează, dar nici reciclarea discului nu este vizibilă, dar pentru orice eventualitate, a fost făcută o încercare de a activa cache-ul row_cache_size_in_mb = 2048 și de a seta caching = {'keys': 'ALL', 'rows_per_partition': '2000000'}, dar asta a înrăutățit situația.

De asemenea, merită menționat încă o dată un punct important despre numărul de regiuni din HB. În cazul nostru, valoarea a fost specificată ca 64. Dacă o reduceți și o faceți egală, de exemplu, cu 4, atunci când citiți, viteza scade de 2 ori. Motivul este că memstore se va umple mai repede și fișierele vor fi spălate mai des, iar la citire, vor trebui procesate mai multe fișiere, ceea ce este o operațiune destul de complicată pentru HB. În condiții reale, acest lucru poate fi tratat prin gândirea unei strategii de presplitting și compactare, în special, folosim un utilitar auto-scris care colectează gunoiul și comprimă fișierele HF în mod constant; Este foarte posibil ca pentru testele DataStax să fi alocat doar 1 regiune per tabel (ceea ce nu este corect) și asta ar clarifica oarecum de ce HB a fost atât de inferior la testele lor de citire.

Din aceasta se desprind următoarele concluzii preliminare. Presupunând că nu au fost făcute greșeli majore în timpul testării, atunci Cassandra arată ca un colos cu picioare de lut. Mai exact, în timp ce se echilibrează pe un picior, ca în poza de la începutul articolului, dă rezultate relativ bune, dar într-o luptă în aceleași condiții pierde definitiv. În același timp, ținând cont de utilizarea scăzută a CPU pe hardware-ul nostru, am învățat să plantăm două RegionServer HB-uri pe gazdă și, prin urmare, am dublat performanța. Acestea. Ținând cont de utilizarea resurselor, situația pentru CS este și mai deplorabilă.

Desigur, aceste teste sunt destul de sintetice și cantitatea de date care a fost folosită aici este relativ modestă. Este posibil ca dacă am trece la terabytes, situația ar fi diferită, dar în timp ce pentru HB putem încărca terabytes, pentru CS acest lucru s-a dovedit a fi problematic. A aruncat adesea o OperationTimedOutException chiar și cu aceste volume, deși parametrii de așteptare a unui răspuns au fost deja măriți de câteva ori față de cei impliciti.

Sper că prin eforturi comune vom găsi blocajele CS și dacă vom putea grăbi, atunci la finalul postării cu siguranță voi adăuga informații despre rezultatele finale.

UPD: Datorită sfatului camarazilor, am reușit să grăbesc lectura. A fost:
159 operațiuni (644 tabele, 4 fluxuri, lot 5).
Adăugat de:
.withLoadBalancingPolicy(noua Politică TokenAware(DCAwareRoundRobinPolicy.builder().build()))
Și m-am jucat cu numărul de fire. Rezultatul este următorul:
4 mese, 100 fire, lot = 1 (bucata cu bucata): 301 operațiuni
4 tabele, 100 fire, lot = 10: 447 operațiuni
4 tabele, 100 fire, lot = 100: 625 operațiuni

Mai târziu voi aplica alte sfaturi de reglare, voi rula un ciclu complet de testare și voi adăuga rezultatele la sfârșitul postării.

Sursa: www.habr.com

Adauga un comentariu