Springboot2集成Ehcache做分布式缓存

本文介绍了Ehcache作为分布式缓存的局限性及其在Springboot中的集成步骤,并对比了Hazelcast的优点,后者提供了更完善的分布式缓存解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Ehcache是一款优秀的缓存中间件,具体介绍可查阅官网http://www.ehcache.org/。目前已经出到3.X版本,但主流的基于Ehcache的分布式缓存方案还是以2.X为主。

Ehcache作为分布式缓存经过测试存在以下两个问题:

1.作为Springboot缓存方案,即通过@Cacheable实现的缓存,只能缓存本地,无法实现分布式。

2.手动可以实现分布式缓存,但没有分布式锁功能,无法实现数据的强一致性。

后来发现存在一种更好的分布式缓存方案——Hazelcast,具体介绍可见官网https://hazelcast.com/。Hazelcast完美地解决了上述问题,因此本文只是对Springboot集成Ehcache做个归档,日后如果需要使用嵌入式的分布式缓存,会使用Hazelcast。

Springboot集成Ehcache步骤如下:

1.添加依赖,包括jgroup分布式缓存依赖和hibernate二级缓存依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>5.4.0.Final</version>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>2.7.4</version>
</dependency>
<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache-jgroupsreplication</artifactId>
    <version>1.7</version>
</dependency>
<dependency>
    <groupId>org.jgroups</groupId>
    <artifactId>jgroups</artifactId>
    <version>3.6.3.Final</version>
</dependency>

2.配置文件ehcache.xml,置于resources目录下

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <diskStore path="java.io.tmpdir/one"/>

    <cacheManagerPeerProviderFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheManagerPeerProviderFactory" properties="connect=UDP(mcast_addr=231.12.21.132;mcast_port=45566):PING:
         MERGE2:FD_SOCK:VERIFY_SUSPECT:pbcast.NAKACK:UNICAST:pbcast.STABLE:FRAG:pbcast.GMS" propertySeparator="::"/>
    <cache name="userCache" maxEntriesLocalHeap="1000" eternal="false" timeToIdleSeconds="100" timeToLiveSeconds="100" overflowToDisk="false">
        <cacheEventListenerFactory class="net.sf.ehcache.distribution.jgroups.JGroupsCacheReplicatorFactory" properties="replicateAsynchronously=false,replicatePuts=true,replicateUpdates=true,replicateUpdatesViaCopy=true,replicateRemovals=true"/>
    </cache>
</ehcache>

3.配置application.properties

#缓存配置
spring.cache.type=ehcache
spring.cache.ehcache.config=classpath:ehcache.xml

#二级缓存
spring.jpa.properties.hibernate.generate_statistics=true
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
spring.jpa.properties.javax.persistence.sharedCache.mode=ENABLE_SELECTIVE

4.测试方法缓存,启动类上添加@EnableCaching

    /**
     * 只具备本地缓存功能,适用场景:不涉及方法外变量和数据库的操作
     */
    @ApiOperation("测试@Cacheable")
    @Cacheable(cacheNames = "userCache", sync = true)
    @GetMapping("/user")
    public User cacheable(@RequestParam("id") long id, @RequestParam("username") String username) throws BizException {
        log.info("没走缓存");
        User user = userRepository.findById(id).orElse(null);
        if (user == null) {
            throw new BizException("id为"+id+"的用户不存在");
        }
        user.setUsername(username);
        log.info(user.toString());
        userRepository.save(user);
        return user;
    }

相同参数请求下,第一次不会走缓存,之后都会走缓存。再起一个相同的服务组成集群,使用相同的参数进行请求,发现第一次也会走缓存,说明这种方式下不支持分布式缓存。

 

5.测试分布式缓存

    @Autowired
    private CacheManager cacheManager;
    /**
     * 分布式缓存需要手动设置
     */
    @ApiOperation("测试分布式缓存")
    @GetMapping("/ehcache")
    public User ehcache(@RequestParam long id) {
        Cache cache = cacheManager.getCache("userCache");
        // 锁只对本地线程有效,分布式下不起作用
        cache.acquireWriteLockOnKey("user");
        Element e = cache.get("user");
        User user;
        if (e == null) {
            log.info("没有使用缓存");
            user = userRepository.findById(id).get();
        } else {
            log.info("使用了缓存");
            user = (User) e.getObjectValue();
        }
        cache.put(new Element("user", user));
        cache.releaseWriteLockOnKey("user");
        return user;
    }

需要注意,此处注入的CacheManager是Ehcache的CacheManager,而不是Springboot的CacheManager。

 

6.测试Ehcache作为二级缓存

在实体类上添加如下注解:

@Cacheable  //实体类二级缓存
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)  //默认可不配

请求时可以在控制台看到查询日志,显示命中率等信息。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值