Запрос Cassandra по вторичному индексу: ReadTimeout: code = 1200

Я использую [cqlsh 5.0.1 | Кассандра 2.2.1 | Спецификация CQL 3.3.0 | Версия собственного протокола v4]. У меня есть 2-узловой кластер cassandra с коэффициентом репликации 2.

$ nodetool status test_keyspace
Datacenter: datacenter1
=======================
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
--  Address       Load       Tokens       Owns (effective)  Host ID                         Rack
UN  10.xxx.4.xxx  85.32 GB   256          100.0%            xxxx-xx-xx-xx-xx                rack1
UN  10.xxx.4.xxx  80.99 GB   256          100.0%            x-xx-xx-xx-xx                   rack1

[Я заменил цифры на x]

Это определение пространства ключей.

cqlsh> describe test_keyspace;

CREATE KEYSPACE test_keyspace WITH replication = {'class': 'SimpleStrategy', 'replication_factor': '2'}  AND durable_writes = true;

CREATE TABLE test_keyspace.test_table (
    id text PRIMARY KEY,
    listids map<int, timestamp>
) WITH bloom_filter_fp_chance = 0.01
    AND caching = '{"keys":"ALL", "rows_per_partition":"NONE"}'
    AND comment = ''
    AND compaction = {'class': 'org.apache.cassandra.db.compaction.SizeTieredCompactionStrategy'}
    AND compression = {'sstable_compression': 'org.apache.cassandra.io.compress.LZ4Compressor'}
    AND dclocal_read_repair_chance = 0.1
    AND default_time_to_live = 0
    AND gc_grace_seconds = 864000
    AND max_index_interval = 2048
    AND memtable_flush_period_in_ms = 0
    AND min_index_interval = 128
    AND read_repair_chance = 0.0
    AND speculative_retry = '99.0PERCENTILE';
CREATE INDEX list_index ON test_keyspace.test_table (keys(listids));

id уникальны, а ключ listids's имеет мощность, близкую к 1000. У меня есть миллионы записей в этом пространстве ключей.

Я хочу получить количество записей с определенным ключом, а также список этих записей. Я попробовал этот запрос из cqlsh:

select count(1) from test_table where listids contains key 12;

Получил эту ошибку через несколько секунд:

ReadTimeout: code=1200 [Coordinator node timed out waiting for replica nodes' responses] message="Operation timed out - received only 0 responses." info={'received_responses': 0, 'required_responses': 1, 'consistency': 'ONE'}

Я уже изменил параметры тайм-аута в cqlshrc и cassandra.yaml.

cat /etc/cassandra/conf/cassandra.yaml | grep read_request_timeout_in_ms
#read_request_timeout_in_ms: 5000
read_request_timeout_in_ms: 300000

cat ~/.cassandra/cqlshrc
[connection]
timeout = 36000
request_timeout = 36000
client_timeout = 36000

Когда я проверил /var/log/cassandra/system.log, я получил только это-

WARN  [SharedPool-Worker-157] 2016-07-25 11:56:22,010 SelectStatement.java:253 - Aggregation query used without partition key

Я использую Java-клиент из своего кода. Java-клиент также получает много тайм-аутов чтения. Одним из решений может быть ремоделирование моих данных, но это займет больше времени (хотя я не уверен в этом). Может ли кто-нибудь предложить быстрое решение этой проблемы?

Добавление статистики:

$ nodetool cfstats test_keyspace
Keyspace: test_keyspace
    Read Count: 5928987886
    Read Latency: 3.468279416568199 ms.
    Write Count: 1590771056
    Write Latency: 0.02020026287239664 ms.
    Pending Flushes: 0
        Table (index): test_table.list_index
        SSTable count: 9
        Space used (live): 9664953448
        Space used (total): 9664953448
        Space used by snapshots (total): 4749
        Off heap memory used (total): 1417400
        SSTable Compression Ratio: 0.822577888909709
        Number of keys (estimate): 108
        Memtable cell count: 672265
        Memtable data size: 30854168
        Memtable off heap memory used: 0
        Memtable switch count: 0
        Local read count: 1718274
        Local read latency: 63.356 ms
        Local write count: 1031719451
        Local write latency: 0.015 ms
        Pending flushes: 0
        Bloom filter false positives: 369
        Bloom filter false ratio: 0.00060
        Bloom filter space used: 592
        Bloom filter off heap memory used: 520
        Index summary off heap memory used: 144
        Compression metadata off heap memory used: 1416736
        Compacted partition minimum bytes: 73
        Compacted partition maximum bytes: 2874382626
        Compacted partition mean bytes: 36905317
        Average live cells per slice (last five minutes): 5389.0
        Maximum live cells per slice (last five minutes): 51012
        Average tombstones per slice (last five minutes): 2.0
        Maximum tombstones per slice (last five minutes): 2759

        Table: test_table
        SSTable count: 559
        Space used (live): 62368820540
        Space used (total): 62368820540
        Space used by snapshots (total): 4794
        Off heap memory used (total): 817427277
        SSTable Compression Ratio: 0.4856571513639344
        Number of keys (estimate): 96692796
        Memtable cell count: 2587248
        Memtable data size: 27398085
        Memtable off heap memory used: 0
        Memtable switch count: 558
        Local read count: 5927272991
        Local read latency: 3.788 ms
        Local write count: 559051606
        Local write latency: 0.037 ms
        Pending flushes: 0
        Bloom filter false positives: 4905594
        Bloom filter false ratio: 0.00023
        Bloom filter space used: 612245816
        Bloom filter off heap memory used: 612241344
        Index summary off heap memory used: 196239565
        Compression metadata off heap memory used: 8946368
        Compacted partition minimum bytes: 43
        Compacted partition maximum bytes: 1916
        Compacted partition mean bytes: 173
        Average live cells per slice (last five minutes): 1.0
        Maximum live cells per slice (last five minutes): 1
        Average tombstones per slice (last five minutes): 1.0
        Maximum tombstones per slice (last five minutes): 1

person Nishant Kumar    schedule 25.07.2016    source источник
comment
Я столкнулся с той же проблемой. пробовал 1) # Также можно установить None для отключения:client_timeout = None в cqlshrc в домашней .cassandra. Не помогло. 2) Увеличил таймаут *timeout_in_ms в ym.cassandra.yaml Тоже не помогло. Наконец, я зациклился на предложении select в своем java-коде и получил счет. 12 миллионов строк дали мне счет за 7 секунд. Это быстро.   -  person Nilesh Deshpande    schedule 15.09.2017


Ответы (2)


Вы можете изменить дизайн своих таблиц или разделить запрос на несколько запросов меньшего размера.

Вы выбираете с использованием вторичного индекса без использования ключа раздела (об этом говорит вам предупреждение). Делая это, вы, по сути, выполняете полное сканирование таблицы. Ваши узлы должны изучить каждый раздел, чтобы выполнить ваш запрос.

Решением без изменения модели данных было бы перебирать все разделы и запускать запрос один раз для каждого раздела.

select count(*) from test_table where id = 'somePartitionId' and listids contains key 12;

Таким образом, ваши узлы знают, в каком разделе вы ищете эту информацию. Затем вам нужно будет агрегировать результаты этих запросов на стороне клиента.

person HashtagMarkus    schedule 25.07.2016
comment
Одно уточнение. В моем случае id должен быть ключом раздела (не уверен), а идентификаторы почти уникальны (также миллионы записей), тогда как я буду запрашивать? - person Nishant Kumar; 26.07.2016
comment
Честно говоря, я бы порекомендовал переделать вашу модель данных. При наличии миллионов разделов вы, конечно, можете запросить каждый раздел отдельно (параллельно), но это, очевидно, займет много времени. - person HashtagMarkus; 26.07.2016

Я столкнулся с той же проблемой. пробовал 1) # Также можно установить None для отключения: client_timeout = None в cqlshrc в домашней .cassandra. Не помогло.

2) Увеличен таймаут *timeout_in_ms в ym.cassandra.yaml

Тоже не помогло. Наконец, я зациклился на предложении select в своем java-коде и получил счет. 12 миллионов строк дали мне счет за 7 секунд. Это быстро.

Cluster cluster = Cluster.builder()
            .addContactPoints(serverIp)
            .build();

     session = cluster.connect(keyspace);


    String cqlStatement = "SELECT count(*) FROM imadmin.device_appclass_attributes";
    //String cqlStatement = "SELECT * FROM system_schema.keyspaces";
    for (Row row : session.execute(cqlStatement)) {
        System.out.println(row.toString());
    }
person Nilesh Deshpande    schedule 15.09.2017