Springboot2集成Ehcache做分布式缓存

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二级缓存依赖


    org.springframework.boot
    spring-boot-starter-cache


    org.hibernate
    hibernate-ehcache
    5.4.0.Final


    net.sf.ehcache
    ehcache
    2.7.4


    net.sf.ehcache
    ehcache-jgroupsreplication
    1.7


    org.jgroups
    jgroups
    3.6.3.Final

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



    

    
    
        
    

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)  //默认可不配

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

你可能感兴趣的:(Springboot2集成Ehcache做分布式缓存)