Cassandra轻量级事务的性能惩罚

3
我有两个Cassandra表,一个记录表和一个计数器表。计数器表为记录表中的每种记录保留一个计数器。
当我向记录表插入新记录时,我将同时更新计数器表。但是可能会出现新记录已经在记录表中的情况。重复插入相同记录是可以的,但这样会使计数器增加两次,这是不正确的。
我现在有两个解决方案。
1. 从Cassandra获取新记录键的记录。如果不为空,我将不插入记录并增加计数器。 2. 使用轻量级事务让Cassandra检查记录是否已经存在。
方案2将使插入操作“原子化”,但文档表示这将影响性能。在方案1中,我发送了两个查询,这也会影响性能。
目前我正在使用方案1。我对Cassandra轻量级事务还不熟悉,所以我不知道原子性的代价。有人知道哪个方案更好吗?
1个回答

7

基本上你有几个选项:

  1. 插入“可信”唯一值 - 你“某种方式”事先知道任何你插入的项目在表中不存在,所以你只需插入并递增计数器而不需要检查任何内容
  2. 使用轻量级事务插入 - 使用IF NOT EXISTS(几乎保证一致性,除了在递增计数器失败/超时时 - 在这种罕见情况下,你可能会遇到低于或高于计数)。此选项允许并发客户端。
  3. 使用一致性级别ONE进行读/写操作(如果你经常运行插入操作,则可能会在写和读之间遇到一致性问题; 同样,请确保没有并发客户端执行相同的操作)
  4. 使用一致性级别QUORUM进行读/写操作(读取将与最后一次写入保持一致,但是,你仍然必须确保没有并发客户端)。

一天,我对一个由m3.large实例组成的三节点Cassandra集群( https://aws.amazon.com/ec2/instance-types/)运行了一个简单的测试。有100个分区和每个分区100次插入(因此总共有10,000次插入)在单个线程中 - 因此这不是一个I/O饱和测试。

架构:

CREATE TABLE IF NOT EXISTS parent_children (
  parentId uuid,
  childId uuid, 
  PRIMARY KEY (parentId, childId)
);

CREATE TABLE IF NOT EXISTS child_counters (
  parentId uuid,
  count counter, 
  PRIMARY KEY (parentId)
);

结果:

Insertion Method    Latency per insert, ms
TRUSTED UNIQUE      1.6404
IF NOT EXISTS       4.2801
READ WRITE ONE      3.9382
READ WRITE QUORUM   3.7714

请注意,法定人数意外地更快,但这可能在误差范围内,或者可能是由于集群拓扑的特定原因。

我想确认一下,在选项3和选项4中,您首先从parent_child读取以测试项目是否存在,然后写入并增加计数器,如果该项目尚不存在,对吗? - Jay
是的。不过根据你的使用情况会有不同的选择。举个例子,如果你想要更新一个已存在的项目,那么你可以执行插入操作(实际上是 upsert),但是跳过计数器的增加。 - yurgis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接