有没有办法修改声明式声明的JCache的过期策略?

时间:2019-08-20 15:22:50

标签: hazelcast jcache jsr107

我正在使用Hazelcast 3.12 jCache实现。我的缓存已声明性声明(通过hazelcast-config.xml),但是我希望能够动态更改ExpiryPolicy的持续时间,因为超时值仅可通过编程获得。

我看过有关ICache的文档,但看不到任何允许我检索和/或修改整个缓存过期策略的方法。

我的缓存声明为:

<cache name="toto">
    <async-backup-count>1</async-backup-count>
    <backup-count>1</backup-count>
    <cache-entry-listeners>
        <cache-entry-listener old-value-required="true">
            <cache-entry-listener-factory class-name="cache.UserRolesEntryListenerStaticFactory"/>
        </cache-entry-listener>
    </cache-entry-listeners>
    <key-type class-name="java.lang.String"/>
    <management-enabled>true</management-enabled>
    <statistics-enabled>true</statistics-enabled>
    <quorum-ref>1</quorum-ref>
    <partition-lost-listeners></partition-lost-listeners>
</cache>

,当我将其设置为以下方式时,我想设置/更新到期政策:

@Produces
@Singleton
@UserRolesCache
public Cache<String, String[]> createUserRoleCache(@HazelcastDistributed CacheManager cacheManager) {
    Cache cache = cacheManager.getCache("toto");

    // get expiry timeout from a 3rd service
    int timeout = configService.getCacheExpiry();

    // how to set the expiry policy here???
    // cache.setExpiryPolicy(.....) ?????
}

使用jCache或Hazelcast API可行吗?

1 个答案:

答案 0 :(得分:3)

没有明确的方法来更改Cache的默认到期策略(在JCache或 特定于Hazelcast的API)。

通过使用自定义Cache配置Factory<ExpiryPolicy>,可以达到相同的效果。 在您的ExpiryPolicy实现中,您可以查询外部服务以查询当前 到期期限并返回该期限,以便JCache实现将其应用。请注意,自到期政策以来 在每次创建/访问/更新条目时都要查询,最好不要使用ExpiryPolicy方法实现 任何远程服务查询或数据库访问,否则您将遇到高延迟。例如, 最好将到期策略注册为外部服务的侦听器(如果支持) 或有一个单独的执行程序来安排对外部服务的查询以进行更新。

使用JCache API的示例实现:

class Scratch {
    public static void main(String[] args)
            throws InterruptedException {
        MutableConfiguration<String, String[]> roleCacheConfig = new MutableConfiguration<>();
        // other config here...
        roleCacheConfig.setExpiryPolicyFactory(new CustomExpiryPolicyFactory());

        CachingProvider provider = Caching.getCachingProvider();
        CacheManager manager = provider.getCacheManager();
        Cache<String, String[]> cache = manager.createCache("test", roleCacheConfig);

        cache.put("a", new String[]{}); // consults getExpiryForCreation
        Thread.sleep(1000);
        cache.get("a"); // consults getExpiryForAccess
        Thread.sleep(1000);
        cache.put("a", new String[]{}); // consults getExpiryForUpdate
    }

    public static class CustomExpiryPolicyFactory implements Factory<ExpiryPolicy>, Serializable {
        @Override
        public ExpiryPolicy create() {
            // initialize custom expiry policy: at this point
            // the custom expiry policy should be registered as listener to
            // external service publishing expiry info or otherwise configured
            // to poll the external service for new expiry info
            CustomExpiryPolicy expiryPolicy = new CustomExpiryPolicy(120, 30, 120);
            return expiryPolicy;
        }
    }

    public static class CustomExpiryPolicy implements ExpiryPolicy {

        private volatile Duration expiryForCreation;
        private volatile Duration expiryForAccess;
        private volatile Duration expiryForUpdate;

        public CustomExpiryPolicy(long secondsForCreation,
                           long secondsForAccess,
                           long secondsForUpdate) {
            this.expiryForCreation = new Duration(TimeUnit.SECONDS, secondsForCreation);
            this.expiryForAccess = new Duration(TimeUnit.SECONDS, secondsForAccess);
            this.expiryForUpdate = new Duration(TimeUnit.SECONDS, secondsForUpdate);
        }

        // assuming this is invoked from external service whenever there is a change
        public void onExpiryChanged(long secondsForCreation,
                                    long secondsForAccess,
                                    long secondsForUpdate) {
            this.expiryForCreation = new Duration(TimeUnit.SECONDS, secondsForCreation);
            this.expiryForAccess = new Duration(TimeUnit.SECONDS, secondsForAccess);
            this.expiryForUpdate = new Duration(TimeUnit.SECONDS, secondsForUpdate);
        }

        @Override
        public Duration getExpiryForCreation() {
            return expiryForCreation;
        }

        @Override
        public Duration getExpiryForAccess() {
            return expiryForAccess;
        }

        @Override
        public Duration getExpiryForUpdate() {
            return expiryForUpdate;
        }
    }
}

您可以在声明性的Hazelcast XML配置中提供自定义的过期策略工厂类名称,如下所示:

<cache name="toto">
    <async-backup-count>1</async-backup-count>
    <backup-count>1</backup-count>
    ...
    <expiry-policy-factory class-name="com.example.cache.CustomExpirePolicyFactory" />
    ...
</cache>

请注意,ICache(Hazelcast特定的扩展Cache界面)中有一些方法可以 您可以使用针对每个键指定的自定义过期策略对一个键或一组键执行操作(但不要更改整个缓存范围内适用的过期策略)。