第 8 章 locking 和 Concurrency


Data Grid 利用多版本的并发控制(MVCC)- 常见用于相关数据库和其他数据存储的并发方案。MVCC 比粗粒度 Java 同步提供了很多优势,甚至 JDK Locks 用于访问共享数据,包括:

  • 允许并发读取器和写入器
  • 读取器和写入者不阻止另一个读者
  • 可以检测和处理写偏移
  • 内部锁定可以被条带化

8.1. 锁定实施详情

网格的 MVCC 实施利用最小锁定和同步,大量采用无锁定技术(如 compare-and-swap 和 lock-free 数据结构),这有助于对多 CPU 和多核心环境进行优化。

特别是,Data Grid 的 MVCC 实现被大量优化用于读取器。读取器线程不会获取条目的显式锁定,而是直接读取问题中的条目。

另一方面,写入者需要获取写锁定。这样可确保每个条目只有一个并发写入器,从而导致并发写入器排队以更改条目。

要允许并发读取,writers 通过在 MVCCEntry 中嵌套条目来制作他们要修改的条目的副本。此副本将并发读取器与看到部分修改的状态隔离。写入完成后,MVCCEntry.commit () 将清除对数据容器的更改,后续读者将看到写入的更改。

8.1.1. 它如何在集群缓存中工作?

在集群缓存中,每个密钥都有一个节点负责锁定密钥。此节点称为主要所有者。

8.1.1.1. 非事务缓存

  1. 写入操作发送到密钥的主所有者。
  2. 主所有者尝试锁定密钥。

    1. 如果成功,它会将操作转发到其他所有者;
    2. 否则,会抛出异常。
注意

如果操作是条件的,且在主所有者上失败,则不会转发到其他所有者。

注意

如果在主所有者中本地执行操作,则将跳过第一步。

8.1.2. 事务缓存

事务缓存支持最佳锁定模式和 pessimistic 锁定模式。如需更多信息,请参阅 Transaction Locking。

8.1.3. 隔离级别

隔离级别会影响与其他事务同时运行时可以读取哪些事务。如需更多信息,请参阅隔离级别。

8.1.4. LockManager

LockManager 是一个组件,负责锁定写入条目。LockManager 使用 LockContainer 来定位/保留/创建锁定。LockContainers 有两个广泛的 flavours,支持锁定条带,支持每个条目一个锁定。

8.1.5. 锁定条带

锁定条带需要对整个缓存使用固定大小、共享锁定集合,并根据条目的键的哈希代码分配给条目。与 JDK 的 ConcurrentHashMap 分配锁定的方式类似,这允许在交换中具有高度可扩展、固定的锁定机制,以便有可能被同一锁阻止相关的条目。

另一种方法是禁用锁定条带 - 这意味着为每个条目 创建新的 锁定。这种方法 可能会 给您带来更高的并发吞吐量,但会牺牲额外的内存用量、垃圾收集混乱等。

默认锁定条带设置

默认禁用锁定条带,因为在不同键的锁定最终在同一锁定条带中时可能会出现的死锁。

可以使用 < locking /> 配置元素的 concurrencyLevel 属性调整锁定条带使用的共享锁定集合的大小。

配置示例:

<locking striping="false|true"/>

或者

new ConfigurationBuilder().locking().useLockStriping(false|true);

8.1.6. 并发级别

除了确定条带锁定容器的大小外,此并发级别还用于调优任何基于 JDK ConcurrentHashMap 的集合,如 DataContainer内部的集合。如需了解并发级别的详细讨论,请参阅 JDK ConcurrentHashMap Javadocs,因为此参数在 Data Grid 中以完全相同的方式使用。

配置示例:

<locking concurrency-level="32"/>

或者

new ConfigurationBuilder().locking().concurrencyLevel(32);

8.1.7. 锁定超时

锁定超时指定内容锁定的时间(以毫秒为单位)。

配置示例:

<locking acquire-timeout="10000"/>

或者

new ConfigurationBuilder().locking().lockAcquisitionTimeout(10000);
//alternatively
new ConfigurationBuilder().locking().lockAcquisitionTimeout(10, TimeUnit.SECONDS);

8.1.8. 一致性

单个所有者被锁定(而不是所有所有者被锁定)不会破坏以下一致性保证:如果密钥 K 被哈希到节点 {A、B} 和事务 TX1 会为 K 获取锁定,让我们表示 A。如果另一个事务( TX2 )在 B (或任何其他节点)上启动,并且 TX2 尝试锁定 K,那么它将因为锁定已经由 TX1 持有而失败。这样做的原因是,关键 K 的锁始终是,确定性,在集群的同一节点上获取,无论事务源自哪里。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.