如何在 cassandra 中制作非原子批处理(或等效)语句

How can I make a non atomic batch (or equivalent) statement in cassandra

我正在使用 Cassandra 的 DataStax Nodejs 驱动程序,我想做的是避免在我的应用程序中插入时发生的非常频繁的 I/O 操作。我将每秒执行大约 1000 次插入,并希望将所有内容组合在一起并执行 1 I/O 而不是 运行 单独的查询,这将导致 1000 I/Os。我遇到了如下的批处理语句,

const query1 = 'UPDATE user_profiles SET email = ? WHERE key = ?';
const query2 = 'INSERT INTO user_track (key, text, date) VALUES (?, ?, ?)';
const queries = [
   { query: query1, params: [emailAddress, 'hendrix'] },
   { query: query2, params: ['hendrix', 'Changed email', new Date()] } 
];
client.batch(queries, { prepare: true }, function (err) {
   // All queries have been executed successfully
   // Or none of the changes have been applied, check err
});

这里的问题是它们是原子的。我希望其他语句成功,即使其中一个语句失败。有什么我可以做的吗?

跨多个分区的批处理语句(您的写入语句就是这种情况)默认使用 LOGGED 批处理。这意味着你有这个原子性属性。如果你真的想删除原子性部分,你应该使用 UNLOGGED 批处理。但是,您应该知道,跨多个分区的 UNLOGGED 批处理是 anti-pattern https://issues.apache.org/jira/browse/CASSANDRA-9282。让我试着解释一下:

当使用批处理语句时,您有 4 种可能的情况:

  • 您的批次是针对单个 分区,还是多个 分区? (这是你的情况)
  • 您的批次使用的是 LOGGED 还是 UNLOGGED 批次? LOGGED 确保原子性(所有或 none 操作都会成功)。 LOGGED 浴缸更贵。

让我们考虑 4 个选项:

  1. 单个 分区,LOGGED 批处理。当您想要针对单个分区实现写入的原子性时,可以使用它。这种原子性是有代价的。所以只有在你需要的时候才使用它。
  2. 单个 分区,UNLOGGED 批处理。当你不需要原子性时使用它,它更快。如果您的应用程序配置正确 (tokenaware),您的批处理语句将选择一个副本(针对此分区)作为协调器,您将获得性能提升。这是使用 UNLOGGED 批处理的唯一正当理由。默认情况下,针对同一分区的批处理是未登录的。
  3. 多个 分区,LOGGED 批次。批量查询命中不同分区的唯一原因是确保原子性。默认情况下,针对多个分区的批处理是 LOGGED。
  4. 多个 分区,UNLOGGED 批次。这是一个 anti-pattern 因为它没有带来任何功能价值(没有原子性),也没有性能优势(涉及多个分区,协调器将有联系负责分区的副本的开销,从而导致额外的工作)。

为了使它更具体,当你跨多个分区发出你所谓的 'a single IO' 批处理语句时,协调器将不得不将你的 'single IO' 分割成 1000 个 IO(它不会如果所有写入都在同一个分区上就是这种情况),并协调跨多个副本。

总而言之,您可能会在客户端观察到性能改进,但会在 Cassandra 端引起更大的成本。

您可能想阅读以下博客 post:http://batey.info/cassandra-anti-pattern-misuse-of.html 特别是针对多个分区使用 UNLOGGED 批处理的部分:

What this is actually doing is putting a huge amount of pressure on a single coordinator. This is because the coordinator needs to forward each individual insert to the correct replicas. You're losing all the benefit of token aware load balancing policy as you're inserting different partitions in a single round trip to the database.