Apache Ignite 2.x – can I take advantage of offheap storage and also still have time based eviction (from the on & off heap storage)?

huangapple go评论96阅读模式
英文:

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:

&lt;bean class=&quot;org.apache.ignite.configuration.CacheConfiguration&quot;&gt;
    &lt;property name=&quot;name&quot; value=&quot;myCache&quot;/&gt;
    &lt;property name=&quot;expiryPolicyFactory&quot;&gt;
        &lt;bean class=&quot;javax.cache.expiry.CreatedExpiryPolicy&quot; factory-method=&quot;factoryOf&quot;&gt;
            &lt;constructor-arg&gt;
                &lt;bean class=&quot;javax.cache.expiry.Duration&quot;&gt;
                    &lt;constructor-arg value=&quot;MINUTES&quot;/&gt;
                    &lt;constructor-arg value=&quot;5&quot;/&gt;
                &lt;/bean&gt;
            &lt;/constructor-arg&gt;
        &lt;/bean&gt;
   &lt;/property&gt;
&lt;/bean&gt;

(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

根据您的代码和解释,我了解到您可能对淘汰策略和过期策略有些困惑。

  1. 淘汰策略确定在内存不足时应从 RAM 中移除哪些数据。
  2. 过期策略用于确定缓存条目的 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.

  1. Eviction policy determines which data should be removed from RAM if RAM runs out.
  2. 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() + &quot;Organizations&quot;;
public static void main(String[] args) throws Exception {
DataRegionConfiguration dfltDataRegConf = new DataRegionConfiguration();
dfltDataRegConf.setPersistenceEnabled(true);
DataStorageConfiguration dsCfg = new DataStorageConfiguration();
dsCfg.setDefaultDataRegionConfiguration(dfltDataRegConf);
dsCfg.setStoragePath(&quot;/home/kazakov/tmp&quot;);
IgniteConfiguration igniteConfiguration = new IgniteConfiguration();
igniteConfiguration.setDataStorageConfiguration(dsCfg);
TcpDiscoverySpi tcpDiscoverySpi = new TcpDiscoverySpi();
TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder();
ipFinder.setAddresses(Arrays.asList(&quot;127.0.0.1:47500..47509&quot;));
tcpDiscoverySpi.setIpFinder(ipFinder);
igniteConfiguration.setDiscoverySpi(tcpDiscoverySpi);
try(Ignite ignite = Ignition.start(igniteConfiguration)) {
ignite.active(true);
CacheConfiguration&lt;Long, X12File&gt; cacheCfg = new CacheConfiguration&lt;&gt;(ORG_CACHE);
cacheCfg.setCacheMode(CacheMode.REPLICATED);
cacheCfg.setAtomicityMode(CacheAtomicityMode.ATOMIC);
cacheCfg.setBackups(1);
cacheCfg.setOnheapCacheEnabled(true);
IgniteCache&lt;Long, X12File&gt; cache = ignite.getOrCreateCache(cacheCfg).withExpiryPolicy(new CreatedExpiryPolicy(new Duration(TimeUnit.SECONDS, 1)));
for (long i = 0; i &lt; 4_000_000; i++) {
if (i &gt; 0 &amp;&amp; i % 10_000 == 0)
System.out.println(&quot;Done: &quot; + i);
cache.put(i, new X12File(&quot;x12file&quot; + i, LocalDateTime.now().toString()));
}
Thread.sleep(5000);
int matches = 0;
for (long i = 0; i &lt; 4_000_000; i++) {
if (cache.get(i) != null)
++matches;
}
System.out.println(&quot;Matches: &quot; + matches);
}
}

huangapple
  • 本文由 发表于 2020年10月21日 12:13:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/64456578.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定