【问题标题】:Thread-safety of Cassandra BoundStatementCassandra BoundStatement 的线程安全
【发布时间】:2017-04-26 10:25:37
【问题描述】:

This doc guides how to use Cassandra prepared and bound statements.

上面写着:

您应该只准备一次,并将 PreparedStatement 缓存在您的 应用程序(它是线程安全的)。 ... BoundStatement 不是 线程安全。您可以使用不同的方式多次重用一个实例 参数,但仅来自单个线程并且仅当您使用 同步调用:

BoundStatement bound = ps1.bind();

// This is safe:
bound.setString("sku", "324378");
session.execute(bound);

bound.setString("sku", "324379");
session.execute(bound);

// This is NOT SAFE. executeAsync runs concurrently with your code, so the first execution might actually read the
// values after the second setString call, and you would insert 324381 twice:
bound.setString("sku", "324380");
session.executeAsync(bound);

bound.setString("sku", "324381");
session.executeAsync(bound);

很明显上面不是线程安全的,但是如果我们这样改代码:

BoundStatement bound1 = ps1.bind();
BoundStatement bound2 = ps1.bind();

bound1.setString("sku", "324380");
session.executeAsync(bound1);

bound2.setString("sku", "324381");
session.executeAsync(bound2);

即:多个线程使用共同的PreparedStatement,每个线程使用自己的BoundStatement。

1) 这个线程安全吗?

2) 这是否是使用准备好的语句进行并行执行的其他推荐方法?或者 BoundStatements 是否昂贵/创建速度慢/消耗大量内存等原因来保持它们的数量较少?

【问题讨论】:

    标签: java multithreading cassandra thread-safety prepared-statement


    【解决方案1】:

    简短的回答是,如果您想多次使用相同的PreparedStatement 对象,但每次使用不同的BoundStatement 对象限制不同的参数,那么它是线程安全的,因为PreparedStatement 是线程安全的,因此您可以重复使用它有多个线程,BoundStatement 不是线程安全的,所以你每次都有不同的对象。

    为了清楚起见 - 因此,您的线程 1 将使用 ps1 = session.prepare("insert into product (sku, description) values (?, ?)"); 创建您的准备语句,所有其他线程将使用此 ps1 对象来创建自己的 BoundStatement 对象,因为每个线程都有自己的值通过,例如:

    线程 1 将绑定并执行为(注意使用相同的ps1 对象):

    BoundStatement bound = ps1.bind().setString("sku", "001").setString("description", "LCD screen"); 
    session.execute(bound);
    

    线程 2 将绑定并执行为(注意使用相同的ps1 对象):

    BoundStatement bound = ps1.bind().setString("sku", "002").setString("description", "TFT screen"); 
    session.execute(bound);
    

    线程 3 将绑定并执行为(注意使用相同的ps1 对象):

    BoundStatement bound = ps1.bind().setString("sku", "003").setString("description", "LED screen"); 
    session.execute(bound);
    

    简而言之:创建PreparedStatement 对象时会产生主要的性能成本,因为它需要往返于数据库服务器(见下图),因此您可以重复使用它并且它是线程安全的,而您每次都创建一个单独的BoundStatement,因为它不是线程安全的,而且创建它不是一个沉重的对象,并且不要往返于数据库服务器。

    【讨论】:

    • 感谢您的明确答复。希望他们将这条信息添加到下一个版本的 Cassandra 手册中。
    猜你喜欢
    • 2017-12-20
    • 2016-07-03
    • 2021-08-18
    • 2016-05-01
    • 2019-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-30
    相关资源
    最近更新 更多