Redis+Ehcache实现二级缓存

基于SpringBoot版本:2.1.4.RELEASE

 

问:为什么使用二级缓存?

       ☛☛ Redis和Ehcache同为内存存储,但是Redis需要走网络,而Ehcache是本地jvm缓存,速度上Ehcache会更快

       ☛☛ 考虑到Redis极端情况下会出现雪崩,比如多个key在同一段时间内失效,请求直接怼到数据库,可能导致服务雪崩,为了                 避免这种情况发生,最好的解决方案就是使用二级缓存

 

问:Redis和Ehcache谁作为一级缓存比较合适?

       ☛☛ Ehcache是走本地缓存,速度肯定高于Redis,所以使用Ehcache作为一级缓存,完美

 

STEP ONE:SpringBoot整合Redis

这里的内容参考博客:SpringBoot整合Redis

 

STEP TWO:SpringBoot整合Ehcache

☛☛ 导入依赖

<dependency>
	<groupId>net.sf.ehcache</groupId>
	<artifactId>ehcache</artifactId>
</dependency>

☛☛ ehcache.xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<ehcache updateCheck="false" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
	
	<!-- 指定一个文件目录,当EhCache把数据写到硬盘上时,将把数据写到这个文件目录下 -->
	<diskStore path="java.io.tmpdir" />
	
	<!-- name 缓存名称 
	     maxElementsInMemory 设置基于内存缓存可存放对象的最大数目 
	     maxElementsOnDisk 在磁盘上缓存的element的最大数目,默认值为0,表示不限制
	     eternal 如果为true,表示对象永远不会过期 ,false 时为timeToldleSeconds和timeToLiveSeconds 
		 timeToldleSeconds 对象允许处于空闲的最长时间 
		 timeToLiveSeconds 即缓存自创建日期起能够存活的最长时间 
		 overflowToDisk 如果内存中数据超过内存限制,是否要缓存到磁盘上 true表示存在硬盘上 
		 memoryStoreEvictionPolicy 缓存对象清除策略 以下为三种策略 FIFO 先进先出 LFU 一直以来最少被使用策略 LRU 最近最少被使用
	-->
	
	<!-- 默认缓存 -->
	<defaultCache 
	    maxElementsInMemory="1000" 
	    eternal="false"
		timeToIdleSeconds="120" 
		timeToLiveSeconds="120" 
		overflowToDisk="true"
		diskSpoolBufferSizeMB="30" 
		maxElementsOnDisk="10000000"
		diskPersistent="true" 
		diskExpiryThreadIntervalSeconds="120"
		memoryStoreEvictionPolicy="LRU">
	</defaultCache>


     <!--
       defaultCache:默认缓存策略,当ehcache找不到定义的缓存时,则使用这个缓存策略。只能定义一个
       userCache:自定义的缓存,缓存用户信息
     -->
	<cache name="userCache" 
	    maxElementsInMemory="1000" 
	    eternal="false"
		timeToIdleSeconds="10" 
		timeToLiveSeconds="10" 
		overflowToDisk="true"
		diskSpoolBufferSizeMB="30" 
		maxElementsOnDisk="10000000"
		diskPersistent="false" 
		diskExpiryThreadIntervalSeconds="120"
		memoryStoreEvictionPolicy="LRU">
	</cache>
</ehcache>

☛☛ application.properties配置Ehcache

spring.cache.ehcache.config=classpath:ehcache.xml
spring.cache.type = ehcache

☛☛ EhcacheService

public interface EhcacheService {

	// 获取缓存
	public Object get(String cacheName, String key);

	// 放入缓存
	public void put(String cacheName, String key, Object value);

	// 清空缓存
	public void evict(String cacheName, String key);
}

☛☛ EhcacheServiceImpl

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.stereotype.Service;

import com.mote.service.EhcacheService;

@Service("ehcacheService")
public class EhcacheServiceImpl implements EhcacheService {

	@Autowired
	private EhCacheCacheManager cacheCacheManager;

	// 获取缓存
	public Object get(String cacheName, String key) {
		Cache cache = cacheCacheManager.getCacheManager().getCache(cacheName);
		Element element = cache.get(key);
		return element == null ? null : element.getObjectValue();
	}

	// 放入缓存
	public void put(String cacheName, String key, Object value) {
		Cache cache = cacheCacheManager.getCacheManager().getCache(cacheName);
		Element element = new Element(key, value);
		cache.put(element);
	}

	// 清空缓存
	public void evict(String cacheName, String key) {
		Cache cache = cacheCacheManager.getCacheManager().getCache(cacheName);
		cache.remove(key);
	}
}

 

案例代码:根据ID查询一个用户信息

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import com.mote.entity.User;
import com.mote.service.EhcacheService;
import com.mote.service.RedisService;
import com.mote.service.UserService;

@RestController
public class UserController {

	@Autowired
	private UserService userService;

	@Autowired
	private RedisService redisService;

	@Autowired
	private EhcacheService ehcacheService;

	public static final String CACHE_NAME = "userCache";

	@GetMapping("/user/get/{id}")
	public User getUser(@PathVariable("id") int id) {
		try {

			// 定义key
			String key = "key_" + id;

			// 从一级缓存中获取
			User euser = (User) ehcacheService.get(CACHE_NAME, key);
			if (euser != null)
				return euser;
			// 从二级缓存中获取
			User ruser = (User) redisService.get(key);
			if (ruser != null) {
				// 放入一级缓存
				ehcacheService.put(CACHE_NAME, key, ruser);
				return ruser;
			}

			// 从数据库查询
			User user = userService.getUser(id);

			// 放入一级缓存
			ehcacheService.put(CACHE_NAME, key, user);
			// 放入二级缓存
			redisService.set(key, user);
			return user;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值