英文:
Apache Ignite 2.x - can I take advantage of offheap storage and also still have time based eviction (from the on & off heap storage)?
问题
我正在使用Apache Ignite 2.8.1
我有一个特定的缓存,我需要将其存储在堆外内存中(否则我将面临内存不足的问题)。我还需要缓存是分布式的。
但我也希望有一个基于时间的逐出策略,从内存缓存中逐出条目。
在Apache Ignite 2.x中是否可能实现这一点?
查看这里的片段。我已经尝试过各种配置,但除了手动操作之外,没有任何方式可以从缓存中逐出这些条目。
当我运行下面的test
方法时,所有的条目仍然保留在缓存中。
以下是代码片段:
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import javax.cache.expiry.CreatedExpiryPolicy;
import javax.cache.expiry.Duration;
import org.apache.ignite.Ignite;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.eviction.lru.LruEvictionPolicyFactory;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.DataRegionConfiguration;
import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.NearCacheConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
public class IgniteCache {
// ...(代码中的其余部分)
}
这只是Apache Ignite 2.x在我特定的用例中的一个缺点吗?
英文:
I am using Apache Ignite 2.8.1
I have a specific cache that I need to store off heap (because otherwise I will be plagued with out of memory conditions). And I also need the cache to be distributed.
But I also want a time based eviction policy to evict entries from on/off memory cache.
Is this even possible with Apache Ignite 2.x?
See the snippet here. I have tried to configure this every which way, but nothing evicts these entries from the cache except doing it manually.
When I run the test
method below, all the entries remain in the cache.
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import javax.cache.expiry.CreatedExpiryPolicy;
import javax.cache.expiry.Duration;
import org.apache.ignite.Ignite;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.eviction.lru.LruEvictionPolicyFactory;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.configuration.DataRegionConfiguration;
import org.apache.ignite.configuration.DataStorageConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.configuration.NearCacheConfiguration;
import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
public class IgniteCache {
private static final String ORG_CACHE = IgniteCache.class.getSimpleName() + "Organizations";
private static Ignite ignite;
private static org.apache.ignite.IgniteCache cache;
public void start() {
IgniteConfiguration igniteConfiguration = new IgniteConfiguration();
DataStorageConfiguration dsCfg = new DataStorageConfiguration();
DataRegionConfiguration dfltDataRegConf = new DataRegionConfiguration();
dfltDataRegConf.setPersistenceEnabled(true);
dsCfg.setDefaultDataRegionConfiguration(dfltDataRegConf);
dsCfg.setStoragePath("E:\\igniteStorage");
igniteConfiguration.setDataStorageConfiguration(dsCfg);
TcpDiscoverySpi tcpDiscoverySpi = new TcpDiscoverySpi();
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500..47509"));
tcpDiscoverySpi.setIpFinder(ipFinder);
igniteConfiguration.setDiscoverySpi(tcpDiscoverySpi);
ignite = Ignition.start(igniteConfiguration);
ignite.active(true);
CacheConfiguration<Long, X12File> cacheCfg = new CacheConfiguration<>(ORG_CACHE);
cacheCfg.setCacheMode(CacheMode.REPLICATED);
cacheCfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
cacheCfg.setBackups(1);
cacheCfg.setEvictionPolicyFactory(new LruEvictionPolicyFactory<>(50000, 40, 5050)); // this doesn't do anything.
cacheCfg.setNearConfiguration(
new NearCacheConfiguration<Long, X12File>()
.setNearEvictionPolicyFactory(new LruEvictionPolicyFactory<>(1_000_000))); // this doesn't do anything.
cache = ignite.getOrCreateCache(cacheCfg);
for (long i = 0; i < 4_000_000; i++) {
if (i > 0 && i % 10_000 == 0) {
System.out.println("Done: " + i);
}
cache.withExpiryPolicy(new CreatedExpiryPolicy(new Duration(TimeUnit.SECONDS, 1))) // this expiry policy doesn't do anything
.put(i, new X12File("x12file" + i, LocalDateTime.now().toString()));
}
}
public void test() {
System.out.println("Checking if cache entries are being properly evicted ...");
int matches = 0;
for (long i = 0; i < 4_000_000; i++) {
if (cache.get(i) != null) {
++matches;
}
}
System.out.println("Matches: " + matches);
}
}
Is this just a shortcoming of Apache Ignite 2.x in my particular use case?
答案1
得分: 1
简而言之:
- 逐出(Eviction)基于内存。删除某些记录,因为我有太多行或者使用了太多空间
- 过期(Expiry)基于时间。该记录在指定的时间段内没有被访问,因此应当被删除
所有的缓存都是堆外缓存(off-heap)。您可以像这样为缓存配置过期策略:
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="myCache"/>
<property name="expiryPolicyFactory">
<bean class="javax.cache.expiry.CreatedExpiryPolicy" factory-method="factoryOf">
<constructor-arg>
<bean class="javax.cache.expiry.Duration">
<constructor-arg value="MINUTES"/>
<constructor-arg value="5"/>
</bean>
</constructor-arg>
</bean>
</property>
</bean>
(近/on-heap缓存确实会有作用。只是不同于您的预期!它们既在堆内,又在堆外缓存之外工作。)
英文:
In short:
- Eviction is memory-based. Remove some records because I have too many rows or it's using too much space
- Expiry is time-based. This record hasn't been touched for a specified period of time, so it should be removed
All caches are off-heap. You can configure the expiry policy for a cache something like this:
<bean class="org.apache.ignite.configuration.CacheConfiguration">
<property name="name" value="myCache"/>
<property name="expiryPolicyFactory">
<bean class="javax.cache.expiry.CreatedExpiryPolicy" factory-method="factoryOf">
<constructor-arg>
<bean class="javax.cache.expiry.Duration">
<constructor-arg value="MINUTES"/>
<constructor-arg value="5"/>
</bean>
</constructor-arg>
</bean>
</property>
</bean>
(The near/on-heap cache does do something. Just not what you were expecting! They're both on-heap and work in addition to the off-heap cache.)
答案2
得分: 1
根据您的代码和解释,我了解到您可能对淘汰策略和过期策略有些困惑。
- 淘汰策略确定在内存不足时应从 RAM 中移除哪些数据。
- 过期策略用于确定缓存条目的 TTL。
在您的情况下,您只需要过期策略。请看我的示例:
private static final String ORG_CACHE = IgniteCache.class.getSimpleName() + "Organizations";
public static void main(String[] args) throws Exception {
DataRegionConfiguration dfltDataRegConf = new DataRegionConfiguration();
dfltDataRegConf.setPersistenceEnabled(true);
DataStorageConfiguration dsCfg = new DataStorageConfiguration();
dsCfg.setDefaultDataRegionConfiguration(dfltDataRegConf);
dsCfg.setStoragePath("/home/kazakov/tmp");
IgniteConfiguration igniteConfiguration = new IgniteConfiguration();
igniteConfiguration.setDataStorageConfiguration(dsCfg);
TcpDiscoverySpi tcpDiscoverySpi = new TcpDiscoverySpi();
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500..47509"));
tcpDiscoverySpi.setIpFinder(ipFinder);
igniteConfiguration.setDiscoverySpi(tcpDiscoverySpi);
try(Ignite ignite = Ignition.start(igniteConfiguration)) {
ignite.active(true);
CacheConfiguration<Long, X12File> cacheCfg = new CacheConfiguration<>();
cacheCfg.setName(ORG_CACHE);
cacheCfg.setCacheMode(CacheMode.REPLICATED);
cacheCfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
cacheCfg.setBackups(1);
cacheCfg.setOnheapCacheEnabled(true);
IgniteCache<Long, X12File> cache = ignite.getOrCreateCache(cacheCfg)
.withExpiryPolicy(new CreatedExpiryPolicy(new Duration(TimeUnit.SECONDS, 1)));
for (long i = 0; i < 4_000_000; i++) {
if (i > 0 && i % 10_000 == 0)
System.out.println("Done: " + i);
cache.put(i, new X12File("x12file" + i, LocalDateTime.now().toString()));
}
Thread.sleep(5000);
int matches = 0;
for (long i = 0; i < 4_000_000; i++) {
if (cache.get(i) != null)
++matches;
}
System.out.println("Matches: " + matches);
}
}
注意:这是您提供的代码的翻译部分,没有包含任何额外的内容。
英文:
As I understand from your code and from your explanation, it looks like you are a little confused about the Eviction Policies and the Expiry Policies.
- Eviction policy determines which data should be removed from RAM if RAM runs out.
- Expiry policy using for determining TTL of cache entries.
In your case you need only Expiry policy. Look at my example:
private static final String ORG_CACHE = IgniteCache.class.getSimpleName() + "Organizations";
public static void main(String[] args) throws Exception {
DataRegionConfiguration dfltDataRegConf = new DataRegionConfiguration();
dfltDataRegConf.setPersistenceEnabled(true);
DataStorageConfiguration dsCfg = new DataStorageConfiguration();
dsCfg.setDefaultDataRegionConfiguration(dfltDataRegConf);
dsCfg.setStoragePath("/home/kazakov/tmp");
IgniteConfiguration igniteConfiguration = new IgniteConfiguration();
igniteConfiguration.setDataStorageConfiguration(dsCfg);
TcpDiscoverySpi tcpDiscoverySpi = new TcpDiscoverySpi();
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
ipFinder.setAddresses(Arrays.asList("127.0.0.1:47500..47509"));
tcpDiscoverySpi.setIpFinder(ipFinder);
igniteConfiguration.setDiscoverySpi(tcpDiscoverySpi);
try(Ignite ignite = Ignition.start(igniteConfiguration)) {
ignite.active(true);
CacheConfiguration<Long, X12File> cacheCfg = new CacheConfiguration<>(ORG_CACHE);
cacheCfg.setCacheMode(CacheMode.REPLICATED);
cacheCfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
cacheCfg.setBackups(1);
cacheCfg.setOnheapCacheEnabled(true);
IgniteCache<Long, X12File> cache = ignite.getOrCreateCache(cacheCfg).withExpiryPolicy(new CreatedExpiryPolicy(new Duration(TimeUnit.SECONDS, 1)));
for (long i = 0; i < 4_000_000; i++) {
if (i > 0 && i % 10_000 == 0)
System.out.println("Done: " + i);
cache.put(i, new X12File("x12file" + i, LocalDateTime.now().toString()));
}
Thread.sleep(5000);
int matches = 0;
for (long i = 0; i < 4_000_000; i++) {
if (cache.get(i) != null)
++matches;
}
System.out.println("Matches: " + matches);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论