Cassandra中事务存储的建模

时间:2016-09-09 05:30:21

标签: cassandra data-modeling

想知道是否有人可以为我的用例指出Cassandra数据建模问题的良好方向。

假设我们有一个会话的概念,在该会话中,会发生由某些元数据描述的各种事务。可以在给定会话中删除或更新事务。换句话说:

会话ID:

  • 交易A - > {metadata A}
  • 交易B - > {metadata B} ...
  • 交易B' - > {更新了元数据B} ......
  • 已删除交易A ......

有多个正在进行的会话,其中包含OWN交易和元数据列表。

要求是:

  1. 按会话ID +交易ID查询以获取交易元数据
  2. 列出给定会话ID中的所有交易
  3. 我们想到的显而易见的解决方案是使用会话ID进行分区,使用事务ID作为群集密钥。

    然而,这似乎不是一个好主意,因为交易数量可能很大(比方说数百万),每笔交易的元数据也不小(比方说10KB),交易删除也很频繁。我担心如果我使用群集解决方案,行可能变得非常宽,并且由于删除也充满了墓碑。

    有没有人不得不模仿这样的东西?提前谢谢。

2 个答案:

答案 0 :(得分:0)

这看起来有点难。墓碑是你必须与之抗争的东西,但你不能没有它们......

如果您可以删除整个会话及其事务,那么您可以尝试通过创建动态架构模型来减轻墓碑事物的位置,其中您基本上为每个新会话动态创建表并存储在那里与会议有关的一切。那是因为表截断或丢弃不会导致墓碑。请注意,您不应该在模式上创建过多的动态,因为C *的分布式特性会让您失望(例如,正在重建的节点可能比您的“表格切换”花费更长的时间,失败的可能性很小,而且你还在想为什么)。你会卡住并丢失数据。

也许如果您只对最近的百万行感兴趣(例如只有最近5天的行),那么您可以创建6个表,每个活动日一个,一个用于最旧的,具有任何分区和群集配置,并截断最旧的表,避免使用逻辑删除和删除。这实际上取决于你的用例。

修改

您应该能够通过简单地计算特定会话中的交易来控制行的“宽度”:

CREATE TABLE sessions (
    session_id bigint,
    transaction_id bigint,
    splitter bigint,
    transaction_count bigint static,

    ...,
    PRIMARY KEY ((session_id, splitter), transaction_id)
);

CREATE TABLE counters (
    session_id bigint,
    splits counter,
    PRIMARY KEY (session_id)
);

在这里,我采用了一个hypotetical session表并添加了一个splitter字段,这些字段将用于break行的宽度,以及一个静态字段transaction_count将跟踪每个分区中有多少交易。然后,您将跟踪每个会话中有多少splits

为了更清楚,第一次插入这样的数据:

INSERT INTO sessions (session_id, splitter, transaction_id, transaction_count,...) VALUES (0, 0, 0, 1, ...);
INSERT INTO sessions (session_id, splitter, transaction_id, transaction_count,...) VALUES (0, 0, 1, 2, ...);
...
INSERT INTO sessions (session_id, splitter, transaction_id, transaction_count,...) VALUES (0, 0, N, N+1, ...);

当您到达 N 时,无论是10.000还是50.000,您都可以通过创建新的“拆分器”来“切换”分区:

UPDATE counters SET splits = splits + 1 WHERE session_id = 0;

然后继续插入数据:

INSERT INTO sessions (session_id, splitter, transaction_id, transaction_count,...) VALUES (0, 1, N+1, 1, ...);
INSERT INTO sessions (session_id, splitter, transaction_id, transaction_count,...) VALUES (0, 1, N+2, 2, ...);
...
INSERT INTO sessions (session_id, splitter, transaction_id, transaction_count,...) VALUES (0, 1, 2N, N+1, ...);

所以插入很容易。要检索所有内容,您只需执行以下操作:

SELECT splits FROM counters WHERE session_id = 0;

它将返回一个数字 M ,它将告知会话中有多少“分裂”。那你就是:

SELECT * FROM sessions WHERE session_id = 0 AND splitter = 0;
SELECT * FROM sessions WHERE session_id = 0 AND splitter = 1;
...
SELECT * FROM sessions WHERE session_id = 0 AND splitter = M - 1;

但是,如果您需要提取单个交易,则需要找到它,因此在最糟糕的情况下,您需要运行 M 查询。除非你创建一个“反向”表格,告诉你你需要看哪个“分裂”......

希望我足够清楚......

答案 1 :(得分:0)

我猜其中一个选项是使用物化视图来查询会话ID。其余的事务操作将直接操作/访问事务表。

CREATE TABLE transaction (
    session_id     bigint,
    transaction_id bigint,
    ...,
    PRIMARY KEY ((session_id, transaction_id))
);

CREATE MATERIALIZED VIEW session as
SELECT * FROM transactions WHERE session_id IS NOT NULL,
    transaction_id IS NOT NULL
    PRIMARY KEY (session_id, transaction_id);

我看到的唯一问题是无法保证物化视图的一致性,因为它将“最终一致”异步。阅读它可能不是最新的。