繁体   English   中英

在一致性ONE的读取查询期间的Cassandra超时(需要1个响应但仅响应0个副本)

[英]Cassandra timeout during read query at consistency ONE (1 responses were required but only 0 replica responded)

我正在对具有500000行的表进行读取和更新查询,并且在处理大约300000行之后有时会低于错误,即使没有节点关闭也是如此。

在一致性ONE的读取查询期间的Cassandra超时(需要1个响应但仅响应0个副本)

基建细节:
拥有5个Cassandra节点,5个spark和3个Hadoop节点,每个节点有8个内核和28 GB内存,Cassandra 复制因子3

卡桑德拉2.1.8.621 | DSE 4.7.1 | Spark 1.2.1 | Hadoop 2.7.1。

Cassandra配置:

read_request_timeout_in_ms (ms): 10000
range_request_timeout_in_ms (ms): 10000
write_request_timeout_in_ms (ms): 5000
cas_contention_timeout_in_ms (ms): 1000 
truncate_request_timeout_in_ms (ms): 60000
request_timeout_in_ms (ms): 10000.

我通过将read_request_timeout_in_ms (ms)增加到20,000来尝试相同的工作,但它没有帮助。

我正在对两张桌子进行查询。 下面是其中一个表的create语句:

创建表:

CREATE TABLE section_ks.testproblem_section (
    problem_uuid text PRIMARY KEY,
    documentation_date timestamp,
    mapped_code_system text,
    mapped_problem_code text,
    mapped_problem_text text,
    mapped_problem_type_code text,
    mapped_problem_type_text text,
    negation_ind text,
    patient_id text,
    practice_uid text,
    problem_category text,
    problem_code text,
    problem_comment text,
    problem_health_status_code text,
    problem_health_status_text text,
    problem_onset_date timestamp,
    problem_resolution_date timestamp,
    problem_status_code text,
    problem_status_text text,
    problem_text text,
    problem_type_code text,
    problem_type_text text,
    target_site_code text,
    target_site_text text
    ) 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';

查询:

1) SELECT encounter_uuid, encounter_start_date FROM section_ks.encounters WHERE patient_id = '1234' AND encounter_start_date >= '" + formatted_documentation_date + "' ALLOW FILTERING;

2) UPDATE section_ks.encounters SET testproblem_uuid_set = testproblem_uuid_set + {'1256'} WHERE encounter_uuid = 'abcd345';

通常,当您收到超时错误时,这意味着您正在尝试执行在Cassandra中无法正常扩展的操作。 修复通常是修改您的架构。

我建议您在运行查询时监视节点,看看是否可以发现问题区域。 例如,您可以运行“watch -n 1 nodetool tpstats”来查看是否有任何队列正在备份或删除项目。 在此处查看其他监控建议

在您的配置中可能有一件事情就是你说你有五个Cassandra节点,但只有3个火花工人(或者你是说你在每个Cassandra节点上都有三个火花工人?)你至少需要一个火花工人每个Cassandra节点,以便将数据加载到spark中,在每个节点上本地完成,而不是通过网络完成。

如果没有看到您正在运行的架构和查询,就很难说清楚。 你在阅读单个分区吗? 从单个分区读取时,我开始在300,000行附近发生超时错误。 在这里查看问题。 到目前为止,我发现的唯一解决方法是在我的分区键中使用客户端哈希将分区分成大约100K行的较小块。 到目前为止,我还没有找到一种方法告诉Cassandra没有超时的查询,我希望需要很长时间。

不要认为配置是根本原因,而是数据模型问题。

看到section_ks.encounters表的结构会很酷。

建议仔细考虑在设计表结构之前预期要运行的具体查询。

据我所知,这两个查询期望section_ks.encounters的不同结构以良好的性能运行它们。

让我们回顾一下每个提供的查询并尝试设计表:

第一:

SELECT encounter_uuid,encounter_start_date FROM section_ks.encounters WHERE patient_id ='1234'ANDy_start_date> ='“+ formatted_documentation_date +”'ALLOW FILTERING;

  • 第一点,如果Cassandra强迫你添加ALLOW FILTERING,那就是非最佳查询或表结构的符号。
  • 第二点。 首要的关键。 如果patient_id列和encounter_start_date列将形成复合主键,那么关于什么是Cassandra Given查询中的主键的一个很棒的解释将快速并且没有强制ALLOW FILTERING语句。 枚举PRIMARY KEY()语句中的列应该对应于查询中的过滤顺序。
  • 为什么在原始查询中必须允许过滤? 通过分区密钥,Cassandra知道哪个节点数据位于何处。 如果patient_id列不是分区键,Cassandra必须扫描所有5个节点以查找请求的患者。 当我们跨节点有大量数据时,这种全扫描通常会因超时而失败。

以下是表结构与给定查询有效匹配的示例:

create table section_ks.encounters(
    patient_id bigint, 
    encounter_start_date timestamp, 
    encounter_uuid text,
    some_other_non_unique_column text,
    PRIMARY KEY (patient_id, encounter_start_date)
);
  • patient_id列将是“分区键”。 负责跨Cassandra节点的数据分发。 简单来说(省略复制功能):不同范围的患者将存储在不同的节点上。
  • encounter_start_date列将是一个“集群密钥”负责分区内的数据排序。

现在可以从查询中删除允许过滤:

SELECT encounter_uuid, encounter_start_date 
FROM section_ks.encounters 
WHERE patient_id = '1234' AND encounter_start_date >= '2017-08-19';

第二个查询:

UPDATE section_ks.encounters SET testproblem_uuid_set = testproblem_uuid_set + {'1256'} WHERE encounter_uuid ='abcd345';

表结构应该看起来像接近:

create table section_ks.encounters(
    encounter_uuid text, -- partition key
    patient_id bigint,
    testproblem_uuid_set text, 
    some_other_non_unique_column text,
    PRIMARY KEY (encounter_uuid)
);

如果我们明确希望仅通过encounter_uuid进行快速过滤,则应将其定义为分区键。

关于有效数据模型设计的好文章:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM