并发执行 Cassandra 准备语句 returns 无效 JSON 作为结果

Concurrent execution of Cassandra prepared statement returns invalid JSON as result

当我使用准备好的语句异步执行多个语句时,我得到 JSON 损坏的数据。键和值完全损坏。

首先,我在使用自定义脚本对我们的项目进行压力测试时遇到了这个问题。我们正在使用 DataStax C++ 驱动程序并从不同的光纤执行语句。

然后我试图找出问题并编写了简单的 C# 程序,该程序在循环中启动多个任务。每个任务使用一次创建的准备语句从库中读取数据。对于某些行,结果完全是一团糟,例如:

预期(由 cqlsh 获取)

516b00a2-01a7-11e6-8630-c04f49e62c6b |  
lucid_lynx_value_45404 | 
precise_pangolin_value_618429 | 
saucy_salamander_value_302796 |    
trusty_tahr_value_873 | 
vivid_vervet_value_216045 | 
wily_werewolf_value_271991

实际

{
    "sa": "516b00a2-01a7-11e6-8630-c04f49e62c6b", 
    "lucid_lynx": "wily_werewolflue_45404", 
    "precise_pangolin": "precise_pangolin_value_618429", 
    "saucy_salamander": "saucy_salamander_value_302796", 
    "trusty_tahr": "trusty_tahr_value_873", 
    "vivid_vervet": "vivid_vervet_value_216045", 
    "wily_werewolf": "wily_werewolf_value_271991"
}

这是 C# 代码的主要部分。

static void Main(string[] args)
{
  const int task_count = 300;

  using(var cluster = Cluster.Builder().AddContactPoints(/*contact points here*/).Build())
  {
    using(var session = cluster.Connect())
    {
      var prepared = session.Prepare("select json * from test_neptunao.ubuntu where id=?");
      var tasks = new Task[task_count];
      for(int i = 0; i < task_count; i++)
      {
        tasks[i] = Query(prepared, session);
      }
      Task.WaitAll(tasks);
    }
  }
  Console.ReadKey();
}

private static Task Query(PreparedStatement prepared, ISession session)
{
  string id = GetIdOfRandomRow();
  var stmt = prepared.Bind(id);
  stmt.SetConsistencyLevel(ConsistencyLevel.One);
  return session.ExecuteAsync(stmt).ContinueWith(tr =>
  {
    foreach(var row in tr.Result)
    {
      var value = row.GetValue<string>(0);
      //some kind of output
    }
  });
}

带有测试数据库架构的 CQL 脚本。

CREATE KEYSPACE IF NOT EXISTS test_neptunao
WITH replication = {
    'class' : 'SimpleStrategy',
    'replication_factor' : 3
};

use test_neptunao;

create table if not exists ubuntu (
    id timeuuid PRIMARY KEY,
    precise_pangolin text,
    trusty_tahr text,
    wily_werewolf text, 
    vivid_vervet text,
    saucy_salamander text,
    lucid_lynx text
);

UPD

预计JSON

{
    "id": "516b00a2-01a7-11e6-8630-c04f49e62c6b", 
    "lucid_lynx": "lucid_lynx_value_45404", 
    "precise_pangolin": "precise_pangolin_value_618429", 
    "saucy_salamander": "saucy_salamander_value_302796", 
    "trusty_tahr": "trusty_tahr_value_873", 
    "vivid_vervet": "vivid_vervet_value_216045", 
    "wily_werewolf": "wily_werewolf_value_271991"
}

UPD2

这里就是上面提到的sample c# project

UPD3

升级到 Cassandra 3.5 后问题已解决。

我在生成的 JSON 中看到的唯一错误是主键的名称应该是 "id" 而不是 "sa"。否则其他列是正确的。

{
    "sa": "516b00a2-01a7-11e6-8630-c04f49e62c6b", 
    "lucid_lynx": "wily_werewolflue_45404", 
    "precise_pangolin": "precise_pangolin_value_618429", 
    "saucy_salamander": "saucy_salamander_value_302796", 
    "trusty_tahr": "trusty_tahr_value_873", 
    "vivid_vervet": "vivid_vervet_value_216045", 
    "wily_werewolf": "wily_werewolf_value_271991"
}

您希望得到什么样的 JSON 结构?

听起来您看到的是 CASSANDRA-11048(JSON 查询不是线程安全的)。将 Cassandra 升级到具有修复程序的版本是解决此问题的最佳方法。