Trận chiến của hai yakozuna, hay Cassandra vs HBase. Kinh nghiệm của đội Sberbank

Đây thậm chí không phải là một trò đùa, có vẻ như bức tranh cụ thể này phản ánh chính xác nhất bản chất của những cơ sở dữ liệu này và cuối cùng sẽ rõ tại sao:

Trận chiến của hai yakozuna, hay Cassandra vs HBase. Kinh nghiệm của đội Sberbank

Theo Xếp hạng của DB-Engines, hai cơ sở dữ liệu cột NoSQL phổ biến nhất là Cassandra (sau đây gọi là CS) và HBase (HB).

Trận chiến của hai yakozuna, hay Cassandra vs HBase. Kinh nghiệm của đội Sberbank

Theo ý muốn của số phận, nhóm quản lý tải dữ liệu của chúng tôi tại Sberbank đã dài và hợp tác chặt chẽ với HB. Trong thời gian này, chúng tôi đã nghiên cứu khá kỹ điểm mạnh và điểm yếu của nó và học cách nấu nó. Tuy nhiên, sự hiện diện của một giải pháp thay thế dưới hình thức CS luôn buộc chúng tôi phải dằn vặt bản thân một chút với những nghi ngờ: liệu chúng tôi đã lựa chọn đúng? Hơn nữa, kết quả so sánh, do DataStax thực hiện, họ nói rằng CS dễ dàng đánh bại HB với số điểm gần như ấn tượng. Mặt khác, DataStax là một bên quan tâm và bạn không nên tin lời họ. Chúng tôi cũng bối rối trước lượng thông tin khá nhỏ về các điều kiện thử nghiệm, vì vậy chúng tôi quyết định tự mình tìm hiểu xem ai là vua của BigData NoSql và kết quả thu được hóa ra rất thú vị.

Tuy nhiên, trước khi chuyển sang kết quả của các thử nghiệm được thực hiện, cần phải mô tả các khía cạnh quan trọng của cấu hình môi trường. Thực tế là CS có thể được sử dụng ở chế độ cho phép mất dữ liệu. Những thứ kia. đây là khi chỉ có một máy chủ (node) chịu trách nhiệm về dữ liệu của một khóa nhất định và nếu vì lý do nào đó mà nó bị lỗi thì giá trị của khóa này sẽ bị mất. Đối với nhiều nhiệm vụ, điều này không quan trọng, nhưng đối với khu vực ngân hàng thì đây là ngoại lệ chứ không phải là quy luật. Trong trường hợp của chúng tôi, điều quan trọng là phải có nhiều bản sao dữ liệu để lưu trữ đáng tin cậy.

Do đó, chỉ xem xét chế độ vận hành CS ở chế độ sao chép ba lần, tức là. Việc tạo casespace được thực hiện với các tham số sau:

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

Tiếp theo, có hai cách để đảm bảo mức độ nhất quán cần thiết. Nguyên tắc chung:
Tây Bắc + NR > RF

Điều đó có nghĩa là số lượng xác nhận từ các nút khi ghi (NW) cộng với số lượng xác nhận từ các nút khi đọc (NR) phải lớn hơn hệ số sao chép. Trong trường hợp của chúng tôi, RF = 3, có nghĩa là các tùy chọn sau là phù hợp:
2 + 2 > 3
3 + 1 > 3

Vì về cơ bản, điều quan trọng đối với chúng tôi là lưu trữ dữ liệu một cách đáng tin cậy nhất có thể nên sơ đồ 3+1 đã được chọn. Ngoài ra, HB hoạt động theo nguyên tắc tương tự, tức là. sự so sánh như vậy sẽ công bằng hơn.

Cần lưu ý rằng DataStax đã làm điều ngược lại trong nghiên cứu của họ, họ đặt RF = 1 cho cả CS và HB (đối với HB bằng cách thay đổi cài đặt HDFS). Đây là một khía cạnh thực sự quan trọng vì tác động đến hiệu suất CS trong trường hợp này là rất lớn. Ví dụ: hình bên dưới cho thấy thời gian cần thiết để tải dữ liệu vào CS tăng lên:

Trận chiến của hai yakozuna, hay Cassandra vs HBase. Kinh nghiệm của đội Sberbank

Ở đây chúng ta thấy những điều sau: càng có nhiều luồng cạnh tranh ghi dữ liệu thì thời gian ghi càng lâu. Điều này là tự nhiên, nhưng điều quan trọng là mức độ suy giảm hiệu suất đối với RF=3 cao hơn đáng kể. Nói cách khác, nếu chúng ta viết 4 luồng vào 5 bảng mỗi bảng (tổng cộng 20), thì RF=3 sẽ mất khoảng 2 lần (150 giây đối với RF=3 so với 75 đối với RF=1). Nhưng nếu chúng ta tăng tải bằng cách tải dữ liệu vào 8 bảng với 5 luồng mỗi bảng (tổng cộng 40 luồng), thì mức mất RF=3 đã là 2,7 lần (375 giây so với 138).

Có lẽ đây một phần là bí quyết của việc thử nghiệm tải thành công do DataStax thực hiện cho CS, bởi vì đối với HB tại chỗ của chúng tôi, việc thay đổi hệ số sao chép từ 2 thành 3 không có tác dụng gì. Những thứ kia. đĩa không phải là nút cổ chai HB cho cấu hình của chúng tôi. Tuy nhiên, có nhiều cạm bẫy khác ở đây, vì cần lưu ý rằng phiên bản HB của chúng tôi đã được vá và tinh chỉnh một chút, môi trường hoàn toàn khác, v.v. Cũng cần lưu ý rằng có lẽ tôi không biết cách chuẩn bị CS một cách chính xác và có một số cách hiệu quả hơn để làm việc với nó và tôi hy vọng chúng ta sẽ tìm hiểu trong phần nhận xét. Nhưng điều đầu tiên trước tiên.

Tất cả các thử nghiệm được thực hiện trên cụm phần cứng gồm 4 máy chủ, mỗi máy chủ có cấu hình sau:

CPU: Xeon E5-2680 v4 @ 2.40GHz 64 luồng.
Đĩa: 12 ổ cứng SATA
phiên bản java: 1.8.0_111

Phiên bản CS: 3.11.5

tham số cassandra.ymlsố_token: 256
gợi ý_handoff_enabled: đúng
gợi ý_handoff_throttle_in_kb: 1024
max_hints_delivery_threads: 2
gợi ý_thư mục: /data10/cassandra/gợi ý
gợi ý_flush_thời gian_in_ms: 10000
max_hints_file_size_in_mb: 128
batchlog_replay_throttle_in_kb: 1024
trình xác thực: AllowAllAuthenticator
người ủy quyền: AllowAllAuthorizer
role_manager: CassandraRoleManager
vai trò_validity_in_ms: 2000
quyền_validity_in_ms: 2000
thông tin đăng nhập_validity_in_ms: 2000
trình phân vùng: org.apache.cassandra.dht.Murmur3Partitioner
data_file_directories:
- /data1/cassandra/data # mỗi thư mục dataN là một đĩa riêng
- /data2/cassandra/dữ liệu
- /data3/cassandra/dữ liệu
- /data4/cassandra/dữ liệu
- /data5/cassandra/dữ liệu
- /data6/cassandra/dữ liệu
- /data7/cassandra/dữ liệu
- /data8/cassandra/dữ liệu
commitlog_directory: /data9/cassandra/commitlog
cdc_enabled: sai
disk_failure_policy: dừng lại
commit_failure_policy: dừng lại
đã chuẩn bị_statements_cache_size_mb:
tiết kiệm_prepared_statements_cache_size_mb:
key_cache_size_in_mb:
key_cache_save_apse: 14400
row_cache_size_in_mb: 0
row_cache_save_apse: 0
bộ đếm_cache_size_in_mb:
counter_cache_save_apse: 7200
đã lưu_caches_directory:/data10/cassandra/saved_caches
commitlog_sync: định kỳ
cam kết_sync_apse_in_ms: 10000
cam kết_segment_size_in_mb: 32
nhà cung cấp hạt giống:
- tên_lớp: org.apache.cassandra.locator.SimpleSeedProvider
các thông số:
- hạt giống: "*,*"
concurrent_reads: 256 # đã thử 64 - không nhận thấy sự khác biệt
concurrent_writes: 256 # đã thử 64 - không nhận thấy sự khác biệt
concurrent_counter_writes: 256 # đã thử 64 - không nhận thấy sự khác biệt
concurrent_materialized_view_writes: 32
memtable_heap_space_in_mb: 2048 # đã thử 16 GB - chậm hơn
memtable_allocation_type: heap_buffers
index_summary_capacity_in_mb:
chỉ mục_tóm tắt_resize_interval_in_phút: 60
nhỏ giọt_fsync: sai
nhỏ giọt_fsync_interval_in_kb: 10240
cổng_lưu trữ: 7000
ssl_storage_port: 7001
listen_address: *
địa chỉ phát sóng: *
listen_on_broadcast_address: đúng
internode_authenticator: org.apache.cassandra.auth.AllowAllInternodeAuthenticator
start_native_transport: đúng
bản địa_transport_port: 9042
start_rpc: đúng
rpc_address: *
rpc_port: 9160
rpc_keepalive: đúng
rpc_server_type: đồng bộ
tiết kiệm_framed_transport_size_in_mb: 15
gia tăng_backups: sai
ảnh chụp nhanh_trước_compaction: sai
auto_snapshot: đúng
cột_index_size_in_kb: 64
cột_index_cache_size_in_kb: 2
concurrent_compactors: 4
nén_throughput_mb_per_sec: 1600
sstable_preemptive_open_interval_in_mb: 50
read_request_timeout_in_ms: 100000
phạm vi_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
chậm_query_log_timeout_in_ms: 500
cross_node_timeout: sai
endpoint_snitch: GossipingPropertyFileSnitch
Dynamic_snitch_update_interval_in_ms: 100
Dynamic_snitch_reset_interval_in_ms: 600000
động_snitch_badness_threshold: 0.1
request_scheduler: org.apache.cassandra.scheduler.NoScheduler
server_encryption_options:
internode_encryption: không có
client_encryption_options:
đã bật: sai
nén_internode_compression: dc
inter_dc_tcp_nodelay: sai
tracetype_query_ttl: 86400
tracetype_repair_ttl: 604800
Enable_user_d xác định_functions: sai
Enable_scripted_user_d xác định_functions: sai
windows_timer_interval: 1
trong suốt_data_encryption_options:
đã bật: sai
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: sai
Enable_materialized_views: đúng
Enable_sasi_indexes: đúng

Cài đặt GC:

### Cài đặt CMS-XX:+Sử dụngParNewGC
-XX:+Sử dụngConcMarkSweepGC
-XX:+CMSParallelRemarkĐã bật
-XX:Tỷ lệ sống sót=8
-XX:TenuringThreshold tối đa=1
-XX:CMSInitiatingOccupancyPhân số=75
-XX:+Sử dụngCMSBắt đầu chiếm dụngChỉ
-XX:CMSWaitDuration=10000
-XX:+CMSParallelInitialMarkEnabled
-XX:+CMSEdenChunksRecordLuôn luôn
-XX:+CMSClassUnloadingEnabled

Bộ nhớ jvm.options được phân bổ 16Gb (chúng tôi cũng đã thử 32 Gb, không nhận thấy sự khác biệt nào).

Các bảng được tạo bằng lệnh:

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

Phiên bản HB: 1.2.0-cdh5.14.2 (trong lớp org.apache.hadoop.hbase.khu vựcserver.HRegion chúng tôi đã loại trừ MetricsRegion dẫn đến GC khi số lượng vùng lớn hơn 1000 trên RegionServer)

Tham số HBase không mặc địnhngười quản lý vườn thú.session.timeout: 120000
hbase.rpc.timeout: 2 phút
hbase.client.scanner.timeout.thời gian: 2 phút
hbase.master.handler.count: 10
hbase.khu vựcserver.lease.thời gian, hbase.client.scanner.timeout.thời gian: 2 phút
hbase.khu vựcserver.handler.count: 160
hbase.khu vựcserver.metahandler.count: 30
hbase.khu vựcserver.logroll.thời gian: 4 giờ
hbase.khu vựcserver.maxlogs: 200
hbase.hkhu vực.memstore.flush.size: 1 GiB
hbase.hkhu vực.memstore.block.multiplier: 6
hbase.hstore.compactionThreshold: 5
hbase.hstore.blockingStoreFiles: 200
hbase.hzone.majorcompaction: 1 ngày
Đoạn mã cấu hình nâng cao dịch vụ HBase (Van an toàn) cho hbase-site.xml:
hbase.khu vựcserver.wal.codecorg.apache.hadoop.hbase.khu vựcserver.wal.IndexedWALEditCodec
hbase.master.namespace.init.timeout3600000
hbase.khu vựcmáy chủ.tùy chọncacheflushinterval18000000
hbase.khu vựcserver.thread.compaction.large12
hbase.khu vựcserver.wal.enablecompressiontrue
hbase.hstore.compaction.max.size1073741824
hbase.server.compactchecker.interval.multiplier200
Tùy chọn cấu hình Java cho HBase RegionServer:
-XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+CMSParallelRemarkEnabled -XX:ReservedCodeCacheSize=256m
hbase.snapshot.master.timeoutMillis: 2 phút
hbase.snapshot.zone.timeout: 2 phút
hbase.snapshot.master.timeout.millis: 2 phút
Kích thước nhật ký tối đa của máy chủ HBase REST: 100 MiB
Sao lưu tệp nhật ký tối đa của máy chủ HBase REST: 5
Kích thước nhật ký tối đa của máy chủ tiết kiệm HBase: 100 MiB
Sao lưu tệp nhật ký tối đa của máy chủ tiết kiệm HBase: 5
Kích thước nhật ký tối đa chính: 100 MiB
Sao lưu tệp nhật ký tối đa chính: 5
Kích thước nhật ký tối đa của RegionServer: 100 MiB
Sao lưu tệp nhật ký tối đa của RegionServer: 5
Cửa sổ phát hiện chủ hoạt động HBase: 4 phút
dfs.client.hedge.read.threadpool.size: 40
dfs.client.hedged.read.threshold.millis: 10 mili giây
hbase.rest.threads.min: 8
hbase.rest.threads.max: 150
Bộ mô tả tệp quy trình tối đa: 180000
hbase.thrift.minWorkerChủ đề: 200
hbase.master.executor.openkhu vực.threads: 30
hbase.master.executor.closekhu vực.threads: 30
hbase.master.executor.serverops.threads: 60
hbase.khu vựcserver.thread.compaction.small: 6
hbase.ipc.server.read.threadpool.size: 20
Chủ đề Mover khu vực: 6
Kích thước heap Java của máy khách tính bằng byte: 1 GiB
Nhóm mặc định của máy chủ HBase REST: 3 GiB
Nhóm mặc định của máy chủ tiết kiệm HBase: 3 GiB
Kích thước heap Java của HBase Master tính bằng byte: 16 GiB
Kích thước vùng heap Java của Máy chủ vùng HBase tính bằng byte: 32 GiB

+Người giữ vườn thú
maxClientCnxns: 601
maxSessionTimeout: 120000
Tạo bảng:
hbase org.apache.hadoop.hbase.util.RegionSplitter ns:t1 Thống nhấtSplit -c 64 -f cf
thay đổi 'ns:t1', {NAME => 'cf', DATA_BLOCK_ENCODING => 'FAST_DIFF', COMPRESSION => 'GZ'}

Có một điểm quan trọng ở đây - mô tả DataStax không cho biết có bao nhiêu vùng được sử dụng để tạo bảng HB, mặc dù điều này rất quan trọng đối với khối lượng lớn. Do đó, đối với các thử nghiệm, số lượng = 64 đã được chọn, cho phép lưu trữ lên tới 640 GB, tức là. bàn kích thước trung bình.

Vào thời điểm thử nghiệm, HBase có 22 nghìn bảng và 67 nghìn vùng (điều này có thể gây chết người đối với phiên bản 1.2.0 nếu không có bản vá nêu trên).

Bây giờ cho mã. Vì không rõ cấu hình nào có lợi hơn cho một cơ sở dữ liệu cụ thể nên các thử nghiệm đã được thực hiện theo nhiều cách kết hợp khác nhau. Những thứ kia. trong một số thử nghiệm, 4 bảng được tải đồng thời (cả 4 nút đều được sử dụng để kết nối). Trong các thử nghiệm khác, chúng tôi đã làm việc với 8 bảng khác nhau. Trong một số trường hợp, kích thước lô là 100, trong một số trường hợp khác là 200 (tham số lô - xem mã bên dưới). Kích thước dữ liệu cho giá trị là 10 byte hoặc 100 byte (dataSize). Tổng cộng có 5 triệu bản ghi được ghi và đọc vào mỗi bảng mỗi lần. Đồng thời, 5 luồng được ghi/đọc vào mỗi bảng (số luồng - thNum), mỗi luồng sử dụng phạm vi khóa riêng (đếm = 1 triệu):

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

Theo đó, chức năng tương tự đã được cung cấp cho 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);
    }
}

Vì trong HB, khách hàng phải đảm nhiệm việc phân phối dữ liệu đồng đều nên chức năng tạo muối chính trông như thế này:

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

Bây giờ là phần thú vị nhất - kết quả:

Trận chiến của hai yakozuna, hay Cassandra vs HBase. Kinh nghiệm của đội Sberbank

Điều tương tự ở dạng biểu đồ:

Trận chiến của hai yakozuna, hay Cassandra vs HBase. Kinh nghiệm của đội Sberbank

Ưu điểm của HB đáng ngạc nhiên đến mức người ta nghi ngờ rằng có một số loại nút thắt cổ chai nào đó trong quá trình thiết lập CS. Tuy nhiên, Google và tìm kiếm các tham số rõ ràng nhất (như concurrent_writes hoặc memtable_heap_space_in_mb) không tăng tốc mọi thứ. Đồng thời, nhật ký sạch sẽ và không chửi thề bất cứ điều gì.

Dữ liệu được phân bổ đều trên các nút, số liệu thống kê từ tất cả các nút gần như giống nhau.

Đây là giao diện của bảng thống kê từ một trong các nútKhông gian phím: ks
Số lần đọc: 9383707
Độ trễ đọc: 0.04287025042448576 ms
Viết Đếm: 15462012
Độ trễ ghi: 0.1350068438699957 ms
Số lần xả đang chờ xử lý: 0
Bảng: t1
Số SSTable: 16
Dung lượng sử dụng (trực tiếp): 148.59 MiB
Không gian sử dụng (tổng cộng): 148.59 MiB
Dung lượng được sử dụng bởi ảnh chụp nhanh (tổng cộng): 0 byte
Bộ nhớ heap đã sử dụng (tổng cộng): 5.17 MiB
Tỷ lệ nén SSTable: 0.5720989576459437
Số lượng phân vùng (ước tính): 3970323
Số lượng ô có thể ghi nhớ: 0
Kích thước dữ liệu có thể ghi nhớ: 0 byte
Bộ nhớ heap có thể ghi nhớ được sử dụng: 0 byte
Số lần chuyển đổi có thể ghi nhớ: 5
Số lần đọc cục bộ: 2346045
Độ trễ đọc cục bộ: NaN ms
Số lượng ghi cục bộ: 3865503
Độ trễ ghi cục bộ: NaN ms
Đang chờ xử lý: 0
Phần trăm đã sửa chữa: 0.0
Bộ lọc Bloom dương tính giả: 25
Tỷ lệ sai của bộ lọc Bloom: 0.00000
Không gian bộ lọc Bloom được sử dụng: 4.57 MiB
Bộ lọc Bloom loại bỏ bộ nhớ heap được sử dụng: 4.57 MiB
Tóm tắt chỉ mục bộ nhớ heap được sử dụng: 590.02 KiB
Siêu dữ liệu nén ngoài bộ nhớ heap được sử dụng: 19.45 KiB
Số byte tối thiểu của phân vùng được nén: 36
Số byte tối đa của phân vùng được nén: 42
Số byte trung bình của phân vùng được nén: 42
Tế bào sống trung bình trên mỗi lát (năm phút cuối): NaN
Số ô sống tối đa trên mỗi lát (năm phút cuối): 0
Số bia mộ trung bình trên mỗi lát (năm phút cuối): NaN
Số bia mộ tối đa trên mỗi lát (năm phút cuối): 0
Đột biến bị loại bỏ: 0 byte

Nỗ lực giảm kích thước của lô (thậm chí gửi riêng lẻ) không có tác dụng, nó chỉ trở nên tồi tệ hơn. Trên thực tế, có thể đây thực sự là hiệu suất tối đa cho CS, vì kết quả thu được cho CS tương tự như kết quả thu được cho DataStax - khoảng hàng trăm nghìn thao tác mỗi giây. Ngoài ra, nếu nhìn vào việc sử dụng tài nguyên, chúng ta sẽ thấy CS sử dụng nhiều CPU và đĩa hơn:

Trận chiến của hai yakozuna, hay Cassandra vs HBase. Kinh nghiệm của đội Sberbank
Hình này cho thấy mức sử dụng trong quá trình chạy tất cả các thử nghiệm liên tiếp cho cả hai cơ sở dữ liệu.

Về lợi thế đọc mạnh mẽ của HB. Ở đây, bạn có thể thấy rằng đối với cả hai cơ sở dữ liệu, mức sử dụng đĩa trong quá trình đọc là cực kỳ thấp (kiểm tra đọc là phần cuối cùng của chu trình kiểm tra cho mỗi cơ sở dữ liệu, ví dụ đối với CS là từ 15:20 đến 15:40). Trong trường hợp của HB, lý do rất rõ ràng - hầu hết dữ liệu bị treo trong bộ nhớ, trong kho lưu trữ và một số được lưu trong bộ nhớ đệm trong blockcache. Đối với CS, không rõ cách thức hoạt động của nó, nhưng việc tái chế đĩa cũng không hiển thị, nhưng để đề phòng, người ta đã cố gắng kích hoạt bộ nhớ đệm row_cache_size_in_mb = 2048 và đặt caching = {'keys': 'ALL', 'rows_per_partition': ' 2000000'}, nhưng điều đó thậm chí còn tệ hơn một chút.

Cũng cần nhắc lại một lần nữa một điểm quan trọng về số vùng ở HB. Trong trường hợp của chúng tôi, giá trị được chỉ định là 64. Nếu bạn giảm nó và làm cho nó bằng, chẳng hạn như 4, thì khi đọc, tốc độ sẽ giảm đi 2 lần. Nguyên nhân là do memstore sẽ đầy nhanh hơn và các file sẽ bị xóa thường xuyên hơn và khi đọc sẽ cần xử lý nhiều file hơn, đây là một thao tác khá phức tạp đối với HB. Trong điều kiện thực tế, điều này có thể được xử lý bằng cách suy nghĩ thông qua chiến lược phân tách trước và nén; đặc biệt, chúng tôi sử dụng tiện ích tự viết để thu thập rác và nén HFiles liên tục trong nền. Rất có thể đối với các bài kiểm tra DataStax, họ chỉ phân bổ 1 vùng trên mỗi bảng (điều này không chính xác) và điều này phần nào làm rõ lý do tại sao HB lại kém hơn trong các bài kiểm tra đọc của họ.

Từ đó rút ra những kết luận sơ bộ sau đây. Giả sử rằng không có sai sót lớn nào xảy ra trong quá trình thử nghiệm thì Cassandra trông giống như một bức tượng khổng lồ với đôi chân bằng đất sét. Chính xác hơn, trong khi cô ấy giữ thăng bằng bằng một chân, như trong hình ở đầu bài, cô ấy cho kết quả tương đối tốt, nhưng trong một cuộc chiến trong điều kiện tương tự, cô ấy thua trắng. Đồng thời, tính đến mức sử dụng CPU thấp trên phần cứng của mình, chúng tôi đã học cách đặt hai HB của RegionServer trên mỗi máy chủ và nhờ đó tăng gấp đôi hiệu suất. Những thứ kia. Nếu tính đến việc tận dụng tài nguyên thì tình hình CS càng thêm bi đát.

Tất nhiên, những thử nghiệm này khá tổng hợp và lượng dữ liệu được sử dụng ở đây tương đối khiêm tốn. Có thể nếu chúng ta chuyển sang terabyte thì tình hình sẽ khác, nhưng trong khi đối với HB, chúng ta có thể tải terabyte thì đối với CS, điều này hóa ra lại có vấn đề. Nó thường gây ra một ngoại lệ OperationTimedOutException ngay cả với các tập này, mặc dù các tham số chờ phản hồi đã tăng lên nhiều lần so với các tham số mặc định.

Tôi hy vọng rằng thông qua nỗ lực chung, chúng ta sẽ tìm ra những điểm nghẽn của CS và nếu có thể đẩy nhanh tốc độ thì cuối bài tôi chắc chắn sẽ bổ sung thêm thông tin về kết quả cuối cùng.

UPD: Nhờ sự góp ý của các đồng chí nên tôi đã đọc được nhanh hơn. Đã từng là:
159 ops (644 bảng, 4 luồng, lô 5).
CÂU HỎI THƯỜNG GẶP:
.withLoadBalancingPolicy(TokenAwarePolicy mới(DCAwareRoundRobinPolicy.builder().build()))
Và tôi đã chơi đùa với số lượng chủ đề. Kết quả là như sau:
4 bảng, 100 luồng, đợt = 1 (từng mảnh): 301 ops
4 bảng, 100 luồng, lô = 10: 447 op
4 bảng, 100 luồng, lô = 100: 625 op

Sau này tôi sẽ áp dụng các mẹo điều chỉnh khác, chạy một chu trình kiểm tra đầy đủ và thêm kết quả vào cuối bài.

Nguồn: www.habr.com

Thêm một lời nhận xét