【问题标题】:Cassandra gives no data even if data exists即使数据存在,Cassandra 也不提供数据
【发布时间】:2018-05-18 22:03:45
【问题描述】:

我有一个复制因子为 3 的键空间。我将数据插入到 Cassandra(具有单个数据中心的 4 节点集群)中,写入一致性级别为 1。插入完成后,我正在读取具有一致性级别仲裁 (2) 的数据。但是,即使数据存在,有时我也不会获取数据,一段时间后我会使用相同的查询获取数据。我不知道为什么 Cassandra 会这样。

我的列族架构

CREATE TABLE input_data_profile.input_log_profile_1 (
    cid text,
    ctdon bigint,
    ctdat bigint,
    email text,
    addrs set<frozen<udt_addrs>>,
    asset set<frozen<udt_asset>>,
    cntno set<frozen<udt_cntno>>,
    dob frozen<udt_date>,
    dvc set<frozen<udt_dvc>>,
    eaka set<text>,
    edmn text,
    educ set<frozen<udt_educ>>,
    gen tinyint,
    hobby set<text>,
    income set<frozen<udt_income>>,
    interest set<text>,
    lang set<frozen<udt_lang>>,
    levnt set<frozen<udt_levnt>>,
    like map<text, frozen<set<text>>>,
    loc set<frozen<udt_loc>>,
    mapp set<text>,
    name frozen<udt_name>,
    params map<text, frozen<set<text>>>,
    prfsn set<frozen<udt_prfsn>>,
    rel set<frozen<udt_rel>>,
    rel_s tinyint,
    skills_prfsn set<frozen<udt_skill_prfsn>>,
    snw set<frozen<udt_snw>>,
    sport set<text>,
    status tinyint,
    z_addrs tinyint,
    z_asset tinyint,
    z_cntno tinyint,
    z_dob tinyint,
    z_dvc tinyint,
    z_eaka tinyint,
    z_educ tinyint,
    z_email tinyint,
    z_gen tinyint,
    z_hobby tinyint,
    z_income tinyint,
    z_interest tinyint,
    z_lang tinyint,
    z_levnt tinyint,
    z_like tinyint,
    z_loc tinyint,
    z_mapp tinyint,
    z_name tinyint,
    z_params tinyint,
    z_prfsn tinyint,
    z_rel tinyint,
    z_rel_s tinyint,
    z_skills_prfsn tinyint,
    z_snw tinyint,
    z_sport tinyint,
    PRIMARY KEY (cid, ctdon, ctdat, email)
) WITH CLUSTERING ORDER BY (ctdon ASC, ctdat ASC, email ASC)
CREATE INDEX input_log_profile_1_z_snw_idx ON input_data_profile.input_log_profile_1 (z_snw);
CREATE INDEX input_log_profile_1_z_prfsn_idx ON input_data_profile.input_log_profile_1 (z_prfsn);
CREATE INDEX input_log_profile_1_z_hobby_idx ON input_data_profile.input_log_profile_1 (z_hobby);
CREATE INDEX input_log_profile_1_z_rel_idx ON input_data_profile.input_log_profile_1 (z_rel);
CREATE INDEX input_log_profile_1_z_gen_idx ON input_data_profile.input_log_profile_1 (z_gen);
CREATE INDEX input_log_profile_1_z_mapp_idx ON input_data_profile.input_log_profile_1 (z_mapp);
CREATE INDEX input_log_profile_1_z_dvc_idx ON input_data_profile.input_log_profile_1 (z_dvc);
CREATE INDEX input_log_profile_1_z_skills_prfsn_idx ON input_data_profile.input_log_profile_1 (z_skills_prfsn);
CREATE INDEX input_log_profile_1_z_eaka_idx ON input_data_profile.input_log_profile_1 (z_eaka);
CREATE INDEX input_log_profile_1_z_name_idx ON input_data_profile.input_log_profile_1 (z_name);
CREATE INDEX input_log_profile_1_z_cntno_idx ON input_data_profile.input_log_profile_1 (z_cntno);
CREATE INDEX input_log_profile_1_z_educ_idx ON input_data_profile.input_log_profile_1 (z_educ);
CREATE INDEX input_log_profile_1_z_loc_idx ON input_data_profile.input_log_profile_1 (z_loc);
CREATE INDEX input_log_profile_1_z_email_idx ON input_data_profile.input_log_profile_1 (z_email);
CREATE INDEX input_log_profile_1_z_interest_idx ON input_data_profile.input_log_profile_1 (z_interest);
CREATE INDEX input_log_profile_1_z_asset_idx ON input_data_profile.input_log_profile_1 (z_asset);
CREATE INDEX input_log_profile_1_z_like_idx ON input_data_profile.input_log_profile_1 (z_like);
CREATE INDEX input_log_profile_1_z_rel_s_idx ON input_data_profile.input_log_profile_1 (z_rel_s);
CREATE INDEX input_log_profile_1_z_lang_idx ON input_data_profile.input_log_profile_1 (z_lang);
CREATE INDEX input_log_profile_1_z_addrs_idx ON input_data_profile.input_log_profile_1 (z_addrs);
CREATE INDEX input_log_profile_1_z_dob_idx ON input_data_profile.input_log_profile_1 (z_dob);
CREATE INDEX input_log_profile_1_z_income_idx ON input_data_profile.input_log_profile_1 (z_income);
CREATE INDEX input_log_profile_1_z_sport_idx ON input_data_profile.input_log_profile_1 (z_sport);
CREATE INDEX input_log_profile_1_z_params_idx ON input_data_profile.input_log_profile_1 (z_params);

我需要明智地处理字段,因此我索引了每个字段的状态。我想提高读写tps。建议我对架构进行一些修改。

【问题讨论】:

    标签: cassandra cqlsh cassandra-3.0


    【解决方案1】:

    如果我对你的理解正确,那么你真的在这里问了两个问题:

    首先,您使用 CL=1 写入数据并使用 CL=Quorum 读取数据,并想知道为什么您并不总是检索已写入的数据,但稍后可以检索它。如果这是正确的,那么这就是 Cassandra 的预期行为。当使用 CL=1 写入时,响应的 3 个副本中的第一个将向客户端返回成功的写入。如果您在将数据写入其他副本之前尝试使用 Quorum 进行读取,那么您可能无法获得任何(或陈旧)数据返回给您。这是 Cassandra 的最终一致性部分。如果您尝试在成功写入后立即读取数据,那么这可能是导致问题的原因,因为“写入后读取”在 Cassandra 和大多数其他分布式系统中是一种反模式。

    其次,在您的数据架构中,您错误地使用了索引。如果您使用索引来允许您查询这些字段,那么这是一种反模式,尤其是在您拥有大量数据的情况下。 Cassandra 中的索引是一项昂贵的操作,仅应在被索引的列具有低基数的极少数情况下使用。看到这个https://docs.datastax.com/en/cql/3.1/cql/ddl/ddl_when_use_index_c.html

    如果您需要按如此多的列进行查询,那么您需要重新评估您的数据模型,因为 Cassandra 在逐表查询方法上进行了优化,在这种方法中您仅查询主键中的字段。这需要您将数据非规范化到多个不同的表中,以便构建任何具有合理复杂性的应用程序。这是您在选择 Cassandra 提供的性能、高可用性和可扩展性时做出的权衡之一。如果您确实需要对数据执行即席查询的能力,我建议您查看不同的数据存储。

    【讨论】:

    • 插入完成后,只有我在读取数据,所以数据在我读取之前正在复制。其他副本中不可能没有数据。
    • 如果您在 CL=1 写入数据,然后在 CL=Quorum 读取数据,RF=3,则有可能数据正在写入副本 A,但尚未写入到副本 B 或 C。如果您立即读取该数据,您可能会在副本 A(有数据)之前从副本 B 和 C(还没有数据)获得响应。如果您更改读取和写入的 CL=Quorum,则不会发生这种情况。
    猜你喜欢
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 2015-07-28
    • 2015-05-03
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多