
最先来一波redis图片
springboot与ehcache
最近听领导说要实现本地缓存与redis缓存配合使用,提高缓存查询速度问题,领导提起ehcache,自从没有使用过hibernate之后,就没有关注该缓存了,今再拾起研究一番。
引入ehcache
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
添加echache.xml
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd">
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</defaultCache>
<cache name="users"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
maxElementsOnDisk="10000000"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU">
<persistence strategy="localTempSwap"/>
</cache>
</ehcache>
ehcache配置简介
diskStore
这个是磁盘存储路径,当内存缓存满了的时候,就会往这里面放,java.io.tmdir是操作系统缓存的临时目录,不同操作系统缓存目录不一样
maxElementsInMemory
内存缓存中最多可以存放的元素数量,若放入Cache中的元素超过这个数值,则有以下两种情况 1)若overflowToDisk=true,则会将Cache中多出的元素放入磁盘文件中 2)若overflowToDisk=false,则根据memoryStoreEvictionPolicy策略替换Cache中原有的元素
overflowToDisk
内存不足时,是否启用磁盘缓存
eternal
缓存中对象是否永久有效
timeToIdleSeconds
缓存数据在失效前的允许闲置时间(单位:秒),仅当eternal=false时使用,默认值是0表示可闲置时间无穷大,若超过这个时间没有访问此Cache中的某个元素,那么此元素将被从Cache中清除
timeToLiveSeconds
缓存数据的总的存活时间(单位:秒),仅当eternal=false时使用,从创建开始计时,失效结束
maxElementsOnDisk
磁盘缓存中最多可以存放的元素数量,0表示无穷大
diskExpiryThreadIntervalSeconds
磁盘缓存的清理线程运行间隔,默认是120秒
memoryStoreEvictionPolicy
内存存储与释放策略,即达到maxElementsInMemory限制时,Ehcache会根据指定策略清理内存 共有三种策略,分别为LRU(最近最少使用)、LFU(最常用的)、FIFO(先进先出)
application.yml配置
spring:
cache:
type: ehcache
ehcache:
config: classpath:ehcache.xml
缓存操作
缓存的实体对象都必须实现序列化接口(java.io.Serializable)
UserInfo缓存实体对象
package com.example.demo.cache;
import com.alibaba.fastjson.JSON;
import java.io.Serializable;
/**
* @author 飘零的叶子
*/
public class UserInfo implements Serializable {
private static final long serialVersionUID = 2296172282217381086L;
private Long id;
private String username;
private String password;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return JSON.toJSONString(this);
}
}
CacheService缓存操作服务
package com.example.demo.cache;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author 飘零的叶子
*/
@Component
public class CacheService {
private static final ConcurrentHashMap<Long, UserInfo> USER_CACHE = new ConcurrentHashMap<>(64);
private static final String CACHE_NAME = "users";
@CachePut(value = CACHE_NAME, key = "#user.id")
@CacheEvict(value = CACHE_NAME,allEntries = true)
public UserInfo save(UserInfo user) {
System.out.println("保存数据库啦~~~~~ user = " + user);
USER_CACHE.put(user.getId(), user);
return user;
}
@CacheEvict(value = CACHE_NAME,allEntries = true)
public boolean delete(Long id) {
UserInfo userInfo = USER_CACHE.get(id);
System.out.println("删除数据啦 id = " + id + ", userInfo = " + userInfo);
USER_CACHE.remove(id);
return true;
}
@CachePut(value = CACHE_NAME, key = "#user.id")
@CacheEvict(value = CACHE_NAME,allEntries = true)
public UserInfo update(UserInfo user) {
UserInfo old = USER_CACHE.get(user.getId());
System.out.println("更新缓存 user= " + user + ",old = " + old);
USER_CACHE.put(user.getId(), user);
return user;
}
@Cacheable(value = CACHE_NAME, key = "#id")
public UserInfo findOne(Long id) {
UserInfo user = USER_CACHE.get(id);
System.out.println("查询用户信息拉~~~ user = " + user + ",id = " + id);
return user;
}
@Cacheable(value = CACHE_NAME)
public List<UserInfo> findAll() {
System.out.println("查询用户列表啦....");
Set<Map.Entry<Long, UserInfo>> entries = USER_CACHE.entrySet();
List<UserInfo> userList = new ArrayList<>();
for (Map.Entry<Long, UserInfo> entry : entries) {
userList.add(entry.getValue());
}
return userList;
}
}
UserInfoController接口操作类
package com.example.demo.controller;
import com.example.demo.cache.CacheService;
import com.example.demo.cache.UserInfo;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
/**
* @author 飘零的叶子
*/
@RestController
@RequestMapping("/userInfo")
public class UserInfoController {
@Resource
private CacheService cacheService;
@PostMapping("/save")
public UserInfo save(@RequestBody UserInfo user) {
return cacheService.save(user);
}
@GetMapping("/delete/{id}")
public boolean delete(@PathVariable("id") Long id) {
return cacheService.delete(id);
}
@GetMapping("/update")
public UserInfo update(@RequestBody UserInfo user) {
return cacheService.update(user);
}
@GetMapping("/findOne/{id}")
public UserInfo findOne(@PathVariable("id") Long id) {
return cacheService.findOne(id);
}
@GetMapping("/findAll")
public List<UserInfo> findAll() {
return cacheService.findAll();
}
}
启用注解
在Springboot启动类上添加启用缓存注解
@EnableCaching
缓存注解名称解释
@CachePut
保存操作,会将对象信息写入缓存 如: @CachePut(value = CACHE_NAME, key = "#user.id") 1) value为缓存名称 2) key为缓存的key,支持spring el表达式
@CacheEvict(value = CACHE_NAME,allEntries = true)
删除缓存操作,allEntries 设置为true则将相关缓存都清除
@Cacheable(value = CACHE_NAME, key = "#id")
根据key查询缓存信息
@Cacheable(value = CACHE_NAME)
查询所有缓存信息
完结
使用ehcache主要看中其内存缓存,与redis相比其优势就是省去了socket的数据通信交互,直接从内存中获取数据,会比redis获取数据有一定的速度优势;但是ehcache对分布式支持的不太好,在微服务分布式环境下,会造成各自应用的缓存数据不一致。但是对于领导要求的ehcache与redis相结合,刚好满足热数据直接从缓存中拿取的功能,提升调度服务的响应速度。




