Cassandra,并发写入的模式和流程设计

时间:2014-12-01 01:20:35

标签: concurrency cassandra schema

这是一个冗长的问题。它是关于Cassandra架构设计。我来这里是为了获得您尊敬的专家对我正在使用的用例的意见。欢迎所有的意见,建议和评论。这是我的问题。

我们希望从我们的USERS收集有关我们即将发布的一些论文的评论。对于每篇论文,我们寻求3个评论。但我们发送评论邀请给3 * 2 = 6个用户。所有6个用户都可以将他们的评论提交给我们的系统,但只有前3个计数;这些前3位评论者将获得奖励他们的工作。

在我们的Cassandra数据库中,有三个表:USER,PAPER和REVIEW。 USER和PAPER表很简单:每个用户对应USER表中的一行,具有唯一的USER_ID;类似地,每张纸在PAPER表中具有唯一的PAPER_ID。

REVIEW表看起来像这样

CREATE TABLE REVIEW(
    PAPER_ID uuid,
    USER_ID uuid,
    REVIEW_CONTENT text,
    PRIMARY KEY(PAPER_ID, USER_ID)
    );

我们使用PAPER_ID作为REVIEW表的分区键,以便将给定论文的所有评论存储在单个Cassandra行中。对于我们拥有的每篇论文,我们选择6个用户,在REVIEW表中插入6个条目,并向这些用户发送6个邀请。因此,对于纸张" P1",REVIEW表中有6个条目看起来像这样

----------------------------------------------------
PAPER_ID      |  USER_ID        |  REVIEW_CONTENT  |
----------------------------------------------------
 P1           |  U1             |      null        |
----------------------------------------------------
 P1           |  U2             |      null        |
----------------------------------------------------
 P1           |  U3             |      null        |
----------------------------------------------------
 P1           |  U4             |      null        |
----------------------------------------------------
 P1           |  U5             |      null        |
----------------------------------------------------
 P1           |  U6             | This paper   ... |
 ---------------------------------------------------
 ...          |  ...            | ...              |

用户使用http通过网络浏览器提交评论。在后端,我们使用以下流程来处理提交的评论(使用论文" P1"作为示例):

  1. 使用分区键" P1"从REVIEW表中获取所有6个条目。
  2. 在REVIEW_CONTENT列中找出这6个条目中有多少个具有非空值(非空值表示相应的用户已经提交了他的评论。例如,在上表中,用户" U6& #34;已提交了他的评论,而其他5人尚未提交。
  3. 如果此号码> = 3,我们已经有足够的评论,请回复当前评论者,并发送消息,例如"谢谢,我们已经有足够的评论。"
  4. 如果这个数字< 2,将当前评论保存到REVIEW表中的相应条目,返回评论者,并显示消息,例如&#34;您的评论已被接受。&#34; (例如,如果当前评论者是&#34; U1&#34;,则填写&#34; P1,U1&#34;条目的REVIEW_CONTENT列和当前评论内容。)
  5. 如果这个数字= 2,这是最复杂的情​​况,因为当前提交是我们接受的最后一个。在这种情况下,我们首先将当前评论保存到REVIEW表,然后我们找到已提交评论的所有三个用户的ID(包括当前用户),将他们的ID记录到事务表中以便稍后向他们支付奖励。
  6. 但这个过程不起作用。问题是它无法正确处理并发提交。考虑以下情况:两个用户已经提交了他们的评论,同时其他3个用户通过上面显示的三个并发过程提交他们的评论。在步骤5,三者中的每一个都认为他是第三个和最后一个提交者并将新记录插入到交易表中。这会导致重复计算:对于他提交的同一审核,单个用户可能会获得多次奖励。

    此过程的另一个问题是它可能永远不会到达第5步。假设REVIEW表中没有提交,并且4个用户同时提交他们的评论。所有这些人都在第4步保存了他们的评论。之后,后来的提交者将一直被拒绝,因为已经有4个已接受的评论。但由于我们从未到达第5步,因此不会在交易表中记录任何ID,用户将永远不会获得任何奖励。

    所以这就是我的问题:我应该如何处理使用Cassandra作为后端数据库的用例? Cassandra COUNTER会帮忙吗?如果是这样,怎么样?我还没有想过如何使用COUNTER,但是这个博客(http://aphyr.com/posts/294-call-me-maybe-cassandra)警告说Cassandra COUNTER不安全(引用&#34;因此,Cassandra计数器将在大范围内计数过多或不足网络分区。&#34;)Cassandra的比较和设置(CAS)功能会有帮助吗?如果是这样,怎么样?保存博客再次警告说,&#34; Cassandra轻量级交易甚至都不正确。&#34;

1 个答案:

答案 0 :(得分:1)

我不会在评论表中创建空条目,而是考虑将其留空,只在评论提交时填写。要处理并发性,请添加timeuuid字段作为排序键:

CREATE TABLE review(
  paper_id uuid,
  submission_time timeuuid,
  user_id uuid,
  content text,
  PRIMARY KEY (paper_id, submission_time)
);

当用户提交提交时,将该条目添加到表中。然后在写入成功之后,查询表(仅在paper_id上)并找出用户的id是否是前三个中的一个。相应地回应用户。由于您已经承诺了一小部分审阅者,因此获取所有评论的额外开销应该是最小的(特别是因为您不需要在查询中包含内容列)。

如果您需要跟踪哪些人正在查看论文,请在纸质表中添加一组用户ID,并在那里写下六个用户ID。