7.2. 缓存存储实施
Data Grid 提供几个您可以使用的缓存存储实现。或者,您可以提供自定义缓存存储。
7.2.1. Cluster Cache Loaders 复制链接链接已复制到粘贴板!
ClusterCacheLoader
从其他 Data Grid 集群成员检索数据,但不保留数据。换句话说,ClusterCacheLoader
不是缓存存储。
ClusterCacheLoader
提供了一个非阻塞部分替代状态传输。如果本地节点上没有这些密钥,则 ClusterCacheLoader
会从其他节点获取密钥,这与 lazily 加载缓存内容类似。
下图也适用于 ClusterCacheLoader
:
-
预加载不会生效(
preload=true
)。 -
不支持获取持久性状态(
fetch-state=true
)。 - 不支持分段。
ClusterLoader
已被弃用,并将在以后的发行版本中删除。
声明性配置
<persistence> <cluster-loader remote-timeout="500"/> </persistence>
<persistence>
<cluster-loader remote-timeout="500"/>
</persistence>
编程配置
ConfigurationBuilder b = new ConfigurationBuilder(); b.persistence() .addClusterLoader() .remoteCallTimeout(500);
ConfigurationBuilder b = new ConfigurationBuilder();
b.persistence()
.addClusterLoader()
.remoteCallTimeout(500);
7.2.2. 单个文件缓存存储 复制链接链接已复制到粘贴板!
单个文件缓存存储( SingleFileStore
)将数据持久保留到文件。Data Grid 还维护一个键内存中索引,而键和值存储在 文件中。默认情况下,单文件缓存存储被分段,这意味着 Data Grid 为每个网段创建单独的文件。
因为 SingleFileStore
保留了键和值位置的内存索引,所以它需要额外的内存,具体取决于密钥大小和键数。因此,对于密钥大的用例,不建议使用 SingleFileStore
。
在某些情况下,SingleFileStore
也可以变得碎片。如果值的大小持续增加,则不会使用单个文件中的可用空间,但条目会附加到文件的末尾。只有在条目可以容纳它时,才会使用文件中的可用空间。同样,如果您从内存中删除所有条目,则单个文件存储的大小不会减小,或者被碎片整理。
声明性配置
<persistence> <file-store max-entries="5000"/> </persistence>
<persistence>
<file-store max-entries="5000"/>
</persistence>
编程配置
- 对于嵌入式部署,请执行以下操作:
ConfigurationBuilder b = new ConfigurationBuilder(); b.persistence() .addSingleFileStore() .maxEntries(5000);
ConfigurationBuilder b = new ConfigurationBuilder();
b.persistence()
.addSingleFileStore()
.maxEntries(5000);
- 对于服务器部署,请执行以下操作:
分段
单个文件缓存支持分段,并为每个片段创建一个单独的实例,这会在您配置的路径中生成多个目录。每个目录都是代表数据映射的网段的数字。
7.2.3. 基于 JDBC 字符串的缓存存储 复制链接链接已复制到粘贴板!
基于 JDBC 字符串的缓存存储 JdbcStringBasedStore
,使用 JDBC 驱动程序在底层数据库中加载和存储值。
JdbcStringBasedStore
将每个条目存储在表中自己的行中,以提高并发负载的吞吐量。JdbcStringBasedStore
还使用一个简单的一对一映射,它使用 key-to-string-mapper
接口将每个键映射到 String
对象。
Data Grid 提供了一个默认的实现,即 DefaultTwoWayKey2StringMapper
,它处理原语类型。
默认情况下,Data Grid 共享不会被存储,这意味着集群中的所有节点都写入到每个更新上的底层存储。如果只希望操作一次写入底层数据库,您必须将 JDBC 存储配置为共享。
分段
JdbcStringBasedStore
默认使用分段,并且需要数据库表中的列来代表条目所属的网段。
7.2.3.1. connection Factories 复制链接链接已复制到粘贴板!
JdbcStringBasedStore
依赖于 ConnectionFactory
实现来连接数据库。
Data Grid 提供以下 ConnectionFactory
实现:
PooledConnectionFactoryConfigurationBuilder
基于通过 PooledConnectionFactoryConfiguration
配置的 Agroal 的连接工厂。
或者,您可以指定前缀为 org.infinispan.agroal.
的配置属性,如下例所示:
然后,您可以通过 PooledConnectionFactoryConfiguration.propertyFile
将 Data Grid 配置为使用您的属性文件。
您应该将 PooledConnectionFactory
用于独立部署,而不是 servlet 容器中的部署。
ManagedConnectionFactoryConfigurationBuilder
可与受管环境(如应用服务器)一起使用的连接工厂。此连接工厂可以探索 JNDI 树中的可配置位置,并将连接管理委派给 DataSource
。
SimpleConnectionFactoryConfigurationBuilder
一个连接工厂,用于在每个调用时创建数据库连接。您应该只对测试或开发环境使用此连接工厂。
7.2.3.2. 基于 JDBC 字符串的缓存存储配置 复制链接链接已复制到粘贴板!
您可以以编程方式或声明性地配置 JdbcStringBasedStore
。
声明性配置
-
使用
PooledConnectionFactory
-
使用
ManagedConnectionFactory
编程配置
-
使用
PooledConnectionFactory
-
使用
ManagedConnectionFactory
7.2.4. JPA Cache Stores 复制链接链接已复制到粘贴板!
JPA (Java Persistence API)缓存存储、JpaStore
、使用正式模式来持久保留数据。然后,其他应用程序可以从持久性存储中读取,以从 Data Grid 加载数据。但是,其他应用程序不应与 Data Grid 同时使用持久性存储。
使用 JpaStore
时,您应该考虑以下问题:
- 密钥应该是实体的 ID。值应该是实体对象。
-
只允许单个
@Id
或@EmbeddedId
注释。 -
不支持使用
@GeneratedValue
注释自动生成的 ID。 - 所有条目都存储为 immortal。
-
JpaStore
不支持分段。
声明性配置
参数 | 描述 |
---|---|
|
指定 JPA 配置文件 |
| 指定应该存储在此缓存中的完全限定域名。只允许一个类。 |
编程配置
Configuration cacheConfig = new ConfigurationBuilder().persistence() .addStore(JpaStoreConfigurationBuilder.class) .persistenceUnitName("org.infinispan.loaders.jpa.configurationTest") .entityClass(User.class) .build();
Configuration cacheConfig = new ConfigurationBuilder().persistence()
.addStore(JpaStoreConfigurationBuilder.class)
.persistenceUnitName("org.infinispan.loaders.jpa.configurationTest")
.entityClass(User.class)
.build();
参数 | 描述 |
---|---|
|
指定 JPA 配置文件 |
| 指定应该存储在此缓存中的完全限定域名。只允许一个类。 |
7.2.4.1. JPA Cache Store Usage Example 复制链接链接已复制到粘贴板!
本节提供了使用 JPA 缓存存储的示例。
先决条件
-
配置数据网格以汇总您的 JPA 实体。默认情况下,Data Grid 使用 ProtoStream 进行 marshalling Java 对象。要 marshall JPA 实体,您必须创建一个
SerializationContextInitializer
实现,该实现使用SerializationContext
注册.proto
模式和 marshaller。
流程
在
persistence.xml
中定义持久性单元 "my PersistenceUnit"。<persistence-unit name="myPersistenceUnit"> ... </persistence-unit>
<persistence-unit name="myPersistenceUnit"> ... </persistence-unit>
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 创建用户实体类。
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 使用 JPA 缓存存储配置名为"usersCache"的缓存。
然后,您可以将缓存"usersCache"配置为使用 JPA Cache Store,以便在将数据放入缓存中时,数据将基于 JPA 配置保留到数据库中。
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 使用 JPA 缓存存储的缓存只能存储一种类型的数据,如下例所示:
Copy to Clipboard Copied! Toggle word wrap Toggle overflow @EmbeddedId
注释允许您使用复合键,如下例所示:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
7.2.5. 远程缓存存储 复制链接链接已复制到粘贴板!
远程缓存存储 RemoteStore
,使用 Hot Rod 协议在 Data Grid 集群中存储数据。
以下是一个 RemoteStore
配置示例,它将数据存储在两个 Data Grid Server 实例(名为 "one" 和 "two" 的缓存中:
如果您将远程缓存存储配置为共享,则无法预加载数据。换句话说,如果您的配置中是 shared="true"
,则必须设置 preload="false"
。
声明性配置
编程配置
分段
RemoteStore
支持分段,并且可以按网段发布密钥和条目,从而提高批量操作的效率。但是,只有 Data Grid Hot Rod 协议版本 2.3 或更高版本才提供分段。
当您为 RemoteStore
启用分段时,它会使用您在 Data Grid 服务器配置中定义的片段数量。
如果源缓存被分段并使用与 RemoteStore
不同的片段数,则返回不正确的值用于批量操作。在这种情况下,您应该禁用 RemoteStore
的分段。
7.2.6. RocksDB Cache Stores 复制链接链接已复制到粘贴板!
RocksDB 为高并发环境提供具有高性能和可靠性的基于键值的文件系统存储。
RocksDB 缓存存储( RocksDBStore
)使用两个数据库。一个数据库为内存中的数据提供主要缓存存储;其他数据库包含 Data Grid 从内存中过期的条目。
声明性配置
编程配置
参数 | 描述 |
---|---|
| 指定提供主缓存存储的 RocksDB 数据库的路径。如果您没有设置位置,则会自动创建它。请注意,路径必须相对于全局持久位置。 |
| 指定用于为过期数据提供缓存存储的 RocksDB 数据库的路径。如果您没有设置位置,则会自动创建它。请注意,路径必须相对于全局持久位置。 |
| 为过期条目设置内存中队列的大小。当队列达到大小时,Data Grid flushes 已过期到 RocksDB 缓存存储中。 |
| 在删除和重新初始化(re-init) RocksDB 数据库前设置最大条目数。对于较小的缓存存储,迭代所有条目并删除每个条目可以更快速的方法。 |
RocksDB 调优参数
您还可以指定以下 RocksDB 调优参数:
-
compressionType
-
blockSize
-
cacheSize
RocksDB 配置属性
另外,还可在配置中设置属性,如下所示:
-
带有
数据库
的前缀属性,用于调整和调优 RocksDB 数据库。 -
为
数据
添加前缀属性,以配置 RocksDB 存储数据的列系列。
<property name="database.max_background_compactions">2</property> <property name="data.write_buffer_size">64MB</property> <property name="data.compression_per_level">kNoCompression:kNoCompression:kNoCompression:kSnappyCompression:kZSTD:kZSTD</property>
<property name="database.max_background_compactions">2</property>
<property name="data.write_buffer_size">64MB</property>
<property name="data.compression_per_level">kNoCompression:kNoCompression:kNoCompression:kSnappyCompression:kZSTD:kZSTD</property>
分段
RocksDBStore
支持分段,并为每个网段创建单独的列系列。分段 RocksDB 缓存存储提高了查找性能和迭代,但写入操作的性能略低。
您不应该配置超过几百个片段。RocksDB 没有设计为无数列系列。太多片段也会显著增加缓存存储启动时间。
7.2.7. soft-Index 文件存储 复制链接链接已复制到粘贴板!
Soft-Index 文件缓存存储( SoftIndexFileStore
)提供基于文件的本地存储。
SoftIndexFileStore
是一个 Java 实现,它使用使用 Java 软引用缓存内存的 B+ Tree 变体。B+ Tree,名为 Index
,将文件系统上的一个文件卸载到单个文件,每次缓存存储重启时都会进行重新构建。
SoftIndexFileStore
将数据存储在一组文件中,而不是单个文件中。当任何文件使用量低于 50% 时,文件中的条目会被覆盖给另一个文件,然后删除该文件。
SoftIndexFileStore
在一组使用附加方法写入的文件中保留数据。因此,如果您在传统的 magnetic 磁盘中使用 SoftIndexFileStore
,则不需要在编写突发条目时看到它。
SoftIndexFileStore
中的大多数结构都绑定了,因此内存不足异常不会带来风险。您还可以为同时打开文件配置限制。
默认情况下,索引中节点的大小限制为 4096 字节。这个大小还限制密钥长度;更精确地限制序列化密钥的长度。因此,您无法使用超过节点大小的密钥 15 字节。另外,密钥长度存储为 "short",这会将密钥长度限制为 32767 字节。如果键在进行序列化后较长,
SoftIndexFileStore
会抛出异常。
SoftIndexFileStore
无法检测到过期的条目,这可能导致过度使用文件系统中的空间。
AdvancedStore.purgeExpired ()
没有在 SoftIndexFileStore
中实施。
声明性配置
编程配置
ConfigurationBuilder b = new ConfigurationBuilder(); b.persistence() .addStore(SoftIndexFileStoreConfigurationBuilder.class) .indexLocation("testCache/index"); .dataLocation("testCache/data")
ConfigurationBuilder b = new ConfigurationBuilder();
b.persistence()
.addStore(SoftIndexFileStoreConfigurationBuilder.class)
.indexLocation("testCache/index");
.dataLocation("testCache/data")
分段
soft-Index 文件缓存存储支持分段,并为每个片段创建一个单独的实例,这会导致您配置的路径中的多个目录。每个目录都是代表数据映射的网段的数字。
7.2.8. 实施自定义缓存存储 复制链接链接已复制到粘贴板!
您可以通过 Data Grid persistent SPI 创建自定义缓存存储。
7.2.8.1. Data Grid Persistence SPI 复制链接链接已复制到粘贴板!
Data Grid Service Provider Interface (SPI)通过 NonBlockingStore
接口为外部存储启用读取和写入操作,并具有以下功能:
- JCache 兼容供应商的可移植性
-
Data Grid 使用处理阻塞代码的适配器维护
NonBlockingStore
接口和JSR-107
JCache 规格之间的兼容性。 - 简化的事务集成
- Data Grid 会自动处理锁定,因此您的实施不需要协调对持久性存储的并发访问。根据您使用的锁定模式,通常不会发生对同一密钥的并发写入。但是,您应该预期持久性存储上的操作源自多个线程,并创建实施来容许此行为。
- 并行迭代
- 借助 Data Grid,您可以并行迭代具有多个线程的持久性存储中的条目。
- 减少序列化结果,从而减少 CPU 用量
- Data Grid 以序列化格式公开存储的条目,可以远程传输。因此,Data Grid 不需要从持久性存储检索的反序列化条目,然后在写入有线时再次序列化。
7.2.8.2. 创建缓存存储 复制链接链接已复制到粘贴板!
通过实施 NonBlockingStore
接口创建自定义缓存存储。
- 实施适当的 Data Grid 持久 SPI。
-
如果有自定义配置,给存储类标上
@ConfiguredBy
注释。 如果需要,创建自定义缓存存储配置和构建器。
-
扩展
AbstractStoreConfiguration
和AbstractStoreConfigurationBuilder
. (可选)在存储配置类中添加以下注解,以确保您的自定义配置构建器从 XML 解析您的缓存存储配置:
-
@ConfigurationFor
@BuiltBy
如果没有添加这些注解,则
CustomStoreConfigurationBuilder
会解析AbstractStoreConfiguration
中定义的通用存储属性,并且忽略任何其他元素。注意如果配置没有声明
@ConfigurationFor
注释,则 Data Grid 初始化缓存时会记录警告消息。
-
-
扩展
7.2.8.3. 配置数据网格以使用自定义存储 复制链接链接已复制到粘贴板!
创建自定义缓存存储实施后,将 Data Grid 配置为使用它。
声明性配置
<local-cache name="customStoreExample"> <persistence> <store class="org.infinispan.persistence.dummy.DummyInMemoryStore" /> </persistence> </local-cache>
<local-cache name="customStoreExample">
<persistence>
<store class="org.infinispan.persistence.dummy.DummyInMemoryStore" />
</persistence>
</local-cache>
编程配置
Configuration config = new ConfigurationBuilder() .persistence() .addStore(CustomStoreConfigurationBuilder.class) .build();
Configuration config = new ConfigurationBuilder()
.persistence()
.addStore(CustomStoreConfigurationBuilder.class)
.build();
7.2.8.4. 部署自定义缓存存储 复制链接链接已复制到粘贴板!
您可以将自定义缓存打包到 JAR 文件中,并将它们部署到 Data Grid 服务器中,如下所示:
- 将自定义缓存存储实施打包在 JAR 文件中。
-
将您的 JAR 文件添加到 Data Grid 服务器的
server/lib
目录中。