1

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

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
});

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

4

1 回答 1

3

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

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

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

让我们考虑 4 个选项:

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

更具体地说,当您跨多个分区发出所谓的“单个 IO”批处理语句时,协调器无论如何都必须将“单个 IO”分成 1000 个 IO(如果所有写入在同一个分区上),并在多个副本之间进行协调。

总而言之,您可能会观察到客户端的性能有所提高,但您会在 Cassandra 端产生更大的成本。

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

这实际上是给单个协调员施加了巨大的压力。这是因为协调器需要将每个单独的插入转发到正确的副本。当您在数据库的单次往返中插入不同的分区时,您将失去令牌感知负载平衡策略的所有好处。

于 2018-03-24T23:43:13.133 回答