当前位置: 首页 > 知识库问答 >
问题:

并发执行卡桑德拉预准备语句返回无效的 JSON 作为结果

傅兴平
2023-03-14

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

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

然后,我试图隔离这个问题,并编写了一个简单的C#程序,它在一个循环中启动多个Task。每个任务都使用一次创建的prepared语句从基中读取数据。对于某些行,结果完全混乱,例如:

预期(由 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
);

更新

应为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"
}

断续器

这是上面提到的示例c#项目

更新3

升级到Cassandra 3.5后,问题得到解决。

共有2个答案

龙承颜
2023-03-14

我在生成的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结构?

周昊乾
2023-03-14

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

 类似资料:
  • 由于基础设施的限制,我们无法将运行的Cassandra版本升级到 Cassandra现在抛出一个 在这种情况下,最好的解决方法是什么?大多数指南告诉我们简单地使用< code>UNSET:(。

  • 我需要一些帮助来定义使用Cassandra的数据堆垛对象映射器和使用预准备语句的常见解决方案之间的区别。而不是代码将对象映射到POJO类会更干净,在性能等方面还有其他优点。.感谢您的回答。

  • 我使用的是datastax Cassandra 2.0驱动程序,我在使用预先准备好的绑定语句。假设我想查询如下内容: 其中,UUID1、UUID2、UUID3是UUID值。使用绑定语句实现这一点的编程方法是什么?目前,我正在尝试以下方法: 这当前返回了错误的结果。如何正确格式化查询有何建议?

  • 我们对DataStax Cassandra的查询使用缓存的准备声明。但是,如果我们需要向表中添加新列,我们需要重新启动应用程序服务器以重新缓存准备好的语句。 我在卡珊德拉遇到了这个错误,这解释了https://datastax-oss.atlassian.net/browse/JAVA-420的解决方案 它基本上提供了一种解决方法,在查询中不使用“SELECT*FROM table”,而是使用“s

  • 我相信我已经在Cassandra csharp驱动程序(版本2.7.3)的StatementFactory中发现了一个关于如何缓存准备好的语句的逻辑的bug。下面是使用案例。 我们发现,运行此删除后,只有第一个请求成功。在深入了解StatementFactory的源代码之后 您可以看到缓存仅使用 cql 语句。在我们的例子中,我们在不同的键空间(又名会话)中具有相同的表名。两个查询中的 cql 语

  • 我试图使用datastax中的nodejs驱动程序,在cassandra 2.1.2中向用户定义的类型添加一个字段。我在cqlsh中使用<code>ALTER TYPE</code>添加了该字段。当我试图添加一个包含udt的行,并为新字段添加一个值时,它会以空值插入,而不是我提供的值。我强烈怀疑这与集群缓存准备好的语句的方式有关。因为我记得读到准备好的语句是由查询的哈希索引的,所以我尝试更改查询中