第 10 章 配置锁定和并发


Data Grid 使用多版本的并发控制(MVCC)来改进对共享数据的访问。

  • 允许并发读取器和写入器
  • 读取器和写入者不会阻断另一个内容
  • 可以检测到并处理写 skews
  • 内部锁定可以是条带的

10.1. 锁定和并发

多版本的并发控制(MVCC)是一个与关系数据库和其他数据存储流行的并发方案。MVCC 与粗粒度 Java 同步(甚至 JDK Locks)提供了许多优点,以访问共享数据。

Data Grid 的 MVCC 实现利用最小的锁和同步,更倾向于采用无锁定技术,如 比较 和交换以及无锁定数据结构,这有助于针对多 CPU 和多核环境进行优化。

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

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

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

10.1.1. 集群缓存和锁定

在 Data Grid 集群中,主所有者节点负责锁定密钥。

对于非事务缓存,Data Grid 将写操作转发到密钥的主所有者,以便它能够锁定它。然后,Data Grid 将写入操作转发到其他所有者,或者在无法锁定密钥时抛出异常。

注意

如果操作为条件并在主所有者上失败,则 Data Grid 不会将它转发到其他所有者。

对于事务缓存,主所有者可以使用最佳锁定模式锁定密钥。Data Grid 还支持不同的隔离级别,以控制事务之间的并发读取。

10.1.2. LockManager

LockManager 是一个组件,它负责锁定写条目。LockManager 使用 LockContainer 找到/hold/create 锁定。LockContainers 有两个广泛的 flavours,它支持锁定条带,并支持每个条目一个锁定。

10.1.3. 锁定条带

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

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

默认锁定条带设置

默认情况下禁用锁定条带,因为当不同键锁定在同一锁定条带中时可能会出现潜在的死锁。

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

配置示例:

<locking striping="false|true"/>

或者

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

10.1.4. 并发级别

除了确定条带锁定容器的大小外,这个并发级别还用于调整任何基于 JDK ConcurrentHashMap 的集合。有关并发级别的详细讨论,请参阅 JDK ConcurrentHashMap Javadocs,因为此参数在 Data Grid 中完全相同。

配置示例:

<locking concurrency-level="32"/>

或者

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

10.1.5. 锁定超时

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

配置示例:

<locking acquire-timeout="10000"/>

或者

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

10.1.6. 一致性

单个所有者被锁定(而不是所有所有者被锁定)不会破坏以下一致性保证:如果密钥 K 对节点 {A、B} 和事务 TX1 进行哈希处理时,让我们在 A 上取得一个锁定。如果另一个事务 TX2B (或任何其他节点)上启动,TX2 会尝试锁定 K,然后其将失败,因为锁定已持有 TX1。这样做的原因是,无论事务源自的位置,K 的锁始终、确定地获取到集群的同一节点上。

10.1.7. 数据版本控制

Data Grid 支持两种形式的数据版本: simple 和 external。简单的版本控制用于写入偏移检查。

外部版本控制用于在 Data Grid 内封装一个外部的数据源,例如将 Data Grid 与 Hibernate 搭配使用时,后者又直接从数据库获取其数据版本信息。

在这个方案中,传递版本的机制变得有必要,而 put ()putForExternalRead () 的超载版本将在 AdvancedCache 中提供,采用外部数据版本。然后,这存储在 InvocationContext 中,并在提交时应用到条目。

注意

无法编写 skew 检查,在外部数据版本控制时不会执行。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

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

让开源更具包容性

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

關於紅帽

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

© 2024 Red Hat, Inc.