Бітва двух какодзун, або Cassandra vs HBase. Вопыт каманды Ашчадбанка

Гэта нават не жарт, падобна, што менавіта гэтая карцінка найбольш дакладна адлюстроўвае сутнасць гэтых БД, і ў канцы будзе зразумела чаму:

Бітва двух какодзун, або Cassandra vs HBase. Вопыт каманды Ашчадбанка

Згодна з DB-Engines Ranking, дзве самых папулярных NoSQL калоначных базы – гэта Cassandra (далей CS) і HBase (HB).

Бітва двух какодзун, або Cassandra vs HBase. Вопыт каманды Ашчадбанка

Воляю лёсаў наша каманда кіравання загрузкі дадзеных у Ашчадбанку ўжо даўно і шчыльна працуе з HB. За гэты час мы дастаткова добра вывучылі яе моцныя і слабыя бакі і навучыліся яе рыхтаваць. Аднак наяўнасць альтэрнатывы ў выглядзе CS увесь час прымушала крыху раздзіраць сябе сумневамі: а ці правільны выбар мы зрабілі? Тым больш, што вынікі параўнання, выкананага DataStax, казалі, што CS лёгка перамагае HB практычна з разгромным лікам. З іншага боку, DataStax – зацікаўленая асоба, і верыць на слова тут не варта. Таксама бянтэжыла досыць малая колькасць інфармацыі аб умовах тэсціравання, таму мы вырашылі высветліць самастойна, хто ж з'яўляецца каралём BigData NoSql, і атрыманыя вынікі аказаліся вельмі цікавыя.

Аднак перш чым перайсці да вынікаў выкананых тэстаў, неабходна апісаць істотныя аспекты канфігурацый асяроддзя. Справа ў тым, што CS можа выкарыстоўвацца ў рэжыме які дапускае страту дадзеных. Г.зн. гэта калі толькі адзін сервер (нода) адказвае за дадзеныя нейкага ключа і калі ён па нейкім чынніку адваліўся, тое значэнне гэтага ключа будзе страчана. Для многіх задач гэта не крытычна, аднак для банкаўскай сферы гэта хутчэй выключэнне, чым правіла. У нашым выпадку важна мець некалькі копій дадзеных для надзейнага захоўвання.

Таму разглядаўся выключна рэжым працы CS у рэжыме патройнай рэплікацыі, г.зн. стварэнне кейспейса выконвалася з такімі параметрамі:

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

Далей ёсць два спосабы забяспечыць неабходны ўзровень кансістэнтнасці. Агульнае правіла:
NW + NR > RF

Што азначае, што колькасць пацверджанняў ад нод пры запісе (NW) плюс колькасць пацверджанняў ад нод пры чытанні (NR) павінна быць больш фактару рэплікацыі. У нашым выпадку RF = 3 і значыць падыходзяць наступныя варыянты:
2 + 2> 3
3 + 1> 3

Бо нам прынцыпова важна максімальна надзейна захаваць дадзеныя, была абраная схема 3+1. Да таго ж HB працуе па аналагічным прынцыпе, г.зн. такое параўнанне будзе больш сумленным.

Неабходна адзначыць, што DataStax у сваім даследаванні рабілі наадварот, яны ставілі RF = 1 і для CS і для HB (для апошняй шляхам змены налад HDFS). Гэта сапраўды важны аспект, таму што ўплыў на прадукцыйнасць CS у гэтым выпадку велізарнае. Напрыклад, на малюнку ніжэй паказаны рост часу які патрабуецца для загрузкі дадзеных у CS:

Бітва двух какодзун, або Cassandra vs HBase. Вопыт каманды Ашчадбанка

Тут мы бачым наступнае, чым больш канкуруючых плыняў піша дадзеныя, тым даўжэй часу гэта займае. Гэта натуральна, але важна, што пры гэтым дэградацыя прадукцыйнасці для RF=3 істотна вышэй. Іншымі словамі, калі мы пішам у 4 табліцы ў кожную па 5 патокаў (разам 20), то RF=3 прайгравае прыкладна ў 2 разы (150 секунд RF=3 супраць 75 для RF=1). Але калі мы павялічым нагрузку, загружаючы дадзеныя ў 8 табліц у кожную па 5 патокаў (разам 40), то пройгрыш RF=3 ужо ў 2,7 раз (375 секунд супраць 138).

Магчыма, збольшага ў гэтым складаецца сакрэт паспяховага для CS нагрузачнага тэставання выкананага DataStax, таму што для HB на нашым стэндзе змена фактару рэплікацыі з 2 да 3 не аказала ніякага ўплыву. Г.зн. дыскі не з'яўляюцца вузкім месцам для HB для нашай канфігурацыі. Аднак тут ёсць шмат і іншых падводных камянёў, таму што трэба адзначыць, што наша версія HB была крыху пропатчена і зацюнена, асяроддзя зусім розныя і г.д. Таксама варта адзначыць, што магчыма я проста не ведаю, як правільна рыхтаваць CS і існуюць нейкія больш эфектыўныя спосабы працаваць з ёй і спадзяюся ў каментарах мы высветлім гэта. Але пра ўсё па парадку.

Усе тэсты праводзіліся на жалезным кластары які складаецца з 4 сервераў, кожны ў канфігурацыі:

CPU: Xeon E5-2680 v4 @ 2.40GHz 64 threads.
Дыскі: 12 штук SATA HDD
java version: 1.8.0_111

Версія CS: 3.11.5

Параметры cassandra.ymlnum_tokens: 256
hinted_handoff_enabled: true
hinted_handoff_throttle_in_kb: 1024
max_hints_delivery_threads: 2
hints_directory: /data10/cassandra/hints
hints_flush_period_in_ms: 10000
max_hints_file_size_in_mb: 128
batchlog_replay_throttle_in_kb: 1024
authenticator: AllowAllAuthenticator
authorizer: AllowAllAuthorizer
role_manager: CassandraRoleManager
roles_validity_in_ms: 2000
permissions_validity_in_ms: 2000
credentials_validity_in_ms: 2000
partitioner: org.apache.cassandra.dht.Murmur3Partitioner
data_file_directories:
- /data1/cassandra/data # кожная дырэкторыя dataN - асобны дыск
- /data2/cassandra/data
- /data3/cassandra/data
- /data4/cassandra/data
- /data5/cassandra/data
- /data6/cassandra/data
- /data7/cassandra/data
- /data8/cassandra/data
commitlog_directory: /data9/cassandra/commitlog
cdc_enabled: false
disk_failure_policy: stop
commit_failure_policy: stop
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
saved_caches_directory: /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
параметрамі:
- seeds: "*,*"
concurrent_reads: 256 # спрабавалі 64 — розніцы не заўважана
concurrent_writes: 256 # спрабавалі 64 — розніцы не заўважана
concurrent_counter_writes: 256 # спрабавалі 64 — розніцы не заўважана
concurrent_materialized_view_writes: 32
memtable_heap_space_in_mb: 2048 # спрабавалі 16 Гб - было павольней
memtable_allocation_type: heap_buffers
index_summary_capacity_in_mb:
index_summary_resize_interval_in_minutes: 60
trickle_fsync: false
trickle_fsync_interval_in_kb: 10240
storage_port: 7000
ssl_storage_port: 7001
listen_address: *
broadcast_address: *
listen_on_broadcast_address: true
internode_authenticator: org.apache.cassandra.auth.AllowAllInternodeAuthenticator
start_native_transport: true
native_transport_port: 9042
start_rpc: true
rpc_address: *
rpc_port: 9160
rpc_keepalive: true
rpc_server_type: sync
thrift_framed_transport_size_in_mb: 15
incremental_backups: false
snapshot_before_compaction: false
auto_snapshot: true
column_index_size_in_kb: 64
column_index_cache_size_in_kb: 2
concurrent_compactors: 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: false
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: none
client_encryption_options:
enabled: false
internode_compression: dc
inter_dc_tcp_nodelay: false
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:
enabled: 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: false
enable_materialized_views: true
enable_sasi_indexes: true

паводле GC:

### CMS Settings-XX:+UseParNewGC
-XX:+UseConcMarkSweepGC
-XX:+CMSParallelRemarkEnabled
-XX:SurvivorRatio=8
-XX:MaxTenuringThreshold=1
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSWaitDuration=10000
-XX:+CMSParallelInitialMarkEnabled
-XX:+CMSEdenChunksRecordAlways
-XX:+CMSClassUnloadingEnabled

Памяці jvm.options вылучалася 16Gb (яшчэ спрабавалі 32 Gb, розніцы не заўважана).

Стварэнне табліц выконвалася камандай:

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

Версія HB: 1.2.0-cdh5.14.2 (у класе org.apache.hadoop.hbase.regionserver.HRegion намі быў выключаны MetricsRegion які прыводзіў да GC пры кол-ве рэгіёнаў больш 1000 на RegionServer)

Параметры non-default HBasezookeeper.session.timeout: 120000
hbase.rpc.timeout: 2 хвіліны
hbase.client.scanner.timeout.period: 2 minute(s)
hbase.master.handler.count: 10
hbase.regionserver.lease.period, hbase.client.scanner.timeout.period: 2 minute(s)
hbase.regionserver.handler.count: 160
hbase.regionserver.metahandler.count: 30
hbase.regionserver.logroll.period: 4 гадзін(s)
hbase.regionserver.maxlogs: 200
hbase.hregion.memstore.flush.size: 1 GiB
hbase.hregion.memstore.block.multiplier: 6
hbase.hstore.compactionThreshold: 5
hbase.hstore.blockingStoreFiles: 200
hbase.hregion.majorcompaction: 1 дзень(s)
HBase Service Advanced Configuration Snippet (Safety Valve) для 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
Java Configuration Options for HBase RegionServer:
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:ReservedCodeCacheSize=256m
hbase.snapshot.master.timeoutMillis: 2 minute(s)
hbase.snapshot.region.timeout: 2 хвіліны
hbase.snapshot.master.timeout.millis: 2 minute(s)
HBase REST Server Max Log Size: 100 MiB
HBase REST Server Maximum Log File Backups: 5
HBase Thrift Server Max Log Size: 100 MiB
HBase Thrift Server Maximum Log File Backups: 5
Master Max Log Size: 100 MiB
Master Maximum Log File Backups: 5
RegionServer Max Log Size: 100 MiB
RegionServer Maximum Log File Backups: 5
HBase Active Master Detection Window: 4 хвіліны
dfs.client.hedged.read.threadpool.size: 40
dfs.client.hedged.read.threshold.millis: 10 millisecond(s)
hbase.rest.threads.min: 8
hbase.rest.threads.max: 150
Maximum Process File Descriptors: 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
hbase.ipc.server.read.threadpool.size: 20
Region Mover Threads: 6
Client Java Heap Size in Bytes: 1 GiB
HBase REST Server Default Group: 3 GiB
HBase Thrift Server Default Group: 3 GiB
Java Heap Size of HBase Master in Bytes: 16 GiB
Java Heap Size of HBase RegionServer in Bytes: 32 GiB

+ZooKeeper
maxClientCnxns: 601
maxSessionTimeout: 120000
Стварэнне табліц:
hbase org.apache.hadoop.hbase.util.RegionSplitter ns:t1 UniformSplit -c 64 -f cf
alter 'ns:t1', {NAME => 'cf', DATA_BLOCK_ENCODING => 'FAST_DIFF', COMPRESSION => 'GZ'}

Тут ёсць адзін важны момант – у апісанні DataStax не сказана, колькі рэгіёнаў выкарыстоўвалася пры стварэнні табліц HB, хоць гэта крытычна для вялікіх аб'ёмаў. Таму для тэстаў было абрана кол-ць = 64, што дазваляе захоўваць да 640 ГБ, г.зн. табліцу сярэдняга памеру.

У HBase на момант правядзення тэсту было 22 тысячы табліц і 67 тысяч рэгіёнаў (гэта было б забойна для версіі 1.2.0, калі б не патч аб якім сказанае вышэй).

Цяпер што тычыцца кода. Бо не было яснасці, якія канфігурацыі з'яўляюцца больш выйгрышным для той ці іншай БД, тэсты праводзіліся ў розных камбінацыях. Г.зн. у адных тэстах загрузка ішла адначасова ў 4 табліцы (для падлучэння выкарыстоўваліся ўсе 4 ноды). У іншых тэстах працавалі з 8 рознымі табліцамі. У некаторых выпадках памер батча быў роўны 100, у іншых 200 (параметр batch - гл. код ніжэй). Памер даных для value 10 байт або 100 байт (dataSize). Усяго кожны раз запісвалася і вычытвалася па 5 млн. запісаў у кожную табліцу. Пры гэтым у кожную табліцу пісалі/чыталі 5 патокаў (нумар патоку - thNum), кожны з якіх выкарыстаў свой дыяпазон ключоў (count = 1 млн):

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);
    }
}

Адпаведна аналагічны функцыянал быў прадугледжаны для 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);
    }
}

Бо ў HB аб раўнамерным размеркаванні дадзеных павінен клапаціцца кліент, то функцыя салення ключа выглядала так:

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);
}

Цяпер самае цікавае - вынікі:

Бітва двух какодзун, або Cassandra vs HBase. Вопыт каманды Ашчадбанка

Тое самае ў выглядзе графіка:

Бітва двух какодзун, або Cassandra vs HBase. Вопыт каманды Ашчадбанка

Перавага HB настолькі дзіўная, што ёсць падазрэнне аб наяўнасць нейкага вузкага месца ў наладзе CS. Аднак гуглеж і скрут найбольш відавочных параметраў (накшталт concurrent_writes або memtable_heap_space_in_mb) паскарэння не дало. Пры гэтым у логах чыста, ні на што не лаецца.

Дадзеныя ляглі па нодах раўнамерна, статыстыка з усіх нод прыкладна аднолькавая.

Вось як выглядае статыстыка па табліцы з адной з нодKeyspace: ks
Read Count: 9383707
Read Latency: 0.04287025042448576 ms
Write Count: 15462012
Write Latency: 0.1350068438699957 ms
Pending Flushes: 0
Table: t1
SSTable count: 16
Space used (live): 148.59 MiB
Space used (total): 148.59 MiB
Space used by snapshots (total): 0 bytes
Off heap memory used (total): 5.17 MiB
SSTable Compression Ratio: 0.5720989576459437
Number of partitions (estimate): 3970323
Memtable cell count: 0
Memtable data size: 0 bytes
Memtable off heap memory used: 0 bytes
Memtable switch count: 5
Local read count: 2346045
Local read latency: NaN ms
Local write count: 3865503
Local write latency: NaN ms
Pending flushes: 0
Percent repaired: 0.0
Bloom filter false positives: 25
Bloom filter false ratio: 0.00000
Bloom filter space used: 4.57 MiB
Bloom filter off heap memory used: 4.57 MiB
Index summary off heap memory used: 590.02 KiB
Compression metadata off heap memory used: 19.45 KiB
Compacted partition minimum bytes: 36
Compacted partition maximum bytes: 42
Compacted partition mean bytes: 42
Average live cells per slice (last five minutes): NaN
Maximum live cells per slice (last five minutes): 0
Average tombstones per slice (last five minutes): NaN
Maximum tombstones per slice (last five minutes): 0
Dropped Mutations: 0 bytes

Спроба памяншаць памер батча (аж да адпраўкі паштучна) не дала эфекту, стала толькі горш. Магчыма, што насамрэч гэта сапраўды максімум прадукцыйнасці для CS, бо атрыманыя вынікі па CS падобныя на тыя, што атрымаліся і ў DataStax – каля сотні тысяч аперацый у секунду. Акрамя таго, калі паглядзець на ўтылізацыю рэсурсаў, то ўбачым, што CS выкарыстоўвае значна больш і ЦПУ і дыскаў:

Бітва двух какодзун, або Cassandra vs HBase. Вопыт каманды Ашчадбанка
На малюнку паказана ўтылізацыя падчас прагону ўсіх тэстаў запар для абодвух БД.

Што да магутнай перавагі HB пры чытанні. Тут відаць, што для абодвух БД утылізацыя дыскаў пры чытанні вельмі нізкая (тэсты на чытанне гэта завяршальная частка цыклу тэсціравання кожнай БД, напрыклад для CS гэта з 15:20 да 15:40). У выпадку HB прычына зразумелая - вялікая частка дадзеных вісіць у памяці, у memstore і частка закэшавалася ў blockcache. Што да CS, то тут не вельмі ясна як яна ўладкована, аднак таксама ўтылізацыі дыскаў не відаць, але на ўсялякі выпадак была зроблена спроба ўключыць кэш row_cache_size_in_mb = 2048 і ўсталяваны caching = {'keys': 'ALL', 'rows_per_partition': ' 2000000'}, але ад гэтага стала нават крыху горш.

Таксама варта яшчэ раз прагаварыць істотны момант пра колькасць рэгіёнаў у HB. У нашым выпадку было паказана значэнне 64. Калі ж памяншаць яго і зрабіць роўным напрыклад 4, то пры чытанні скорасць падае ў 2 разы. Чыннік у тым, што memstore будзе забівацца хутчэй і файлы будуць флашиться гушчару і пры чытанні трэба будзе апрацоўваць больш файлаў, што для HB досыць складаная аперацыя. У рэальных умовах гэта лечыцца прадумваннем стратэгіі прэсплітынгу і кампафікацыі, у прыватнасці мы выкарыстоўваем самапісную ўтыліту, якая займаецца зборкай смецця і сціскам HFiles увесь час у фонавым рэжыме. Суцэль магчыма, што для тэстаў DataStax вылучалі наогул 1 рэгіён на табліцу (што не правільна) і гэта бы некалькі растлумачыла, чаму HB так прайграваў у іх тэстах на чытанне.

Папярэднія высновы адсюль атрымліваюцца наступныя. Калі дапусціць, што падчас тэсціравання не было дапушчана грубых памылак, то Cassandra падобная на коласа на гліняных нагах. Дакладней, пакуль яна балансуе на адной назе, як на малюнку ў пачатку артыкула, яна паказвае адносна нядрэнныя вынікі, але пры сутычцы ў аднолькавых умовах прайграе ўчыстую. Пры гэтым улічваючы нізкую ўтылізацыю CPU на нашым жалезе мы навучыліся высаджваць па двух RegionServer HB на хост і тым самым падвоілі прадукцыйнасць. Г.зн. з улікам утылізацыі рэсурсаў сітуацыя для CS атрымліваецца яшчэ больш жаласная.

Безумоўна, гэтыя тэсты дастаткова сінтэтычныя і аб'ём дадзеных, які выкарыстоўваўся тут, адносна сціплы. Не выключана, што пры пераходзе на тэрабайты сітуацыя была б іншая, аднак калі для HB мы ўмеем грузіць тэрабайты, то для CS гэта аказалася праблематычна. Яна часцяком выдавала OperationTimedOutException нават пры гэтых аб'ёмах, хоць параметры чакання водгуку і так былі павялічаны ў разы ў параўнанні з дэфолтнымі.

Спадзяюся, што сумеснымі намаганнямі мы знойдзем вузкія месцы CS і калі атрымаецца яе паскорыць, то ў канцы паста абавязкова дадам інфармацыю аб выніковых выніках.

UPD: Дзякуючы парадам камрадаў атрымалася паскорыць чытанне. Было:
159 ops (644 табліцы, 4 патокаў, батч 5).
Паведамленні:
.withLoadBalancingPolicy(new TokenAwarePolicy(DCAwareRoundRobinPolicy.builder().build()))
І пагуляўся з колькасцю патокаў. Атрымалася наступнае:
4 табліцы, 100 патокаў, батч = 1 (паштучна): 301 969 ops
4 табліцы, 100 патокаў, батч = 10: 447 608 ops
4 табліцы, 100 патокаў, батч = 100: 625 655 ops

Пазней ужыву іншыя парады па цюнінгу, праганю поўны цыкл тэставання і дадам вынікі ў канцы посту.

Крыніца: habr.com

Дадаць каментар