16-1 Redis分布式缓存引入与保存缓存功能实现
现在功能已经完成了,但是我们还是要考虑一下性能问题,现在任何请求都是要到数据库中查询很多的数据,才能知道当前的用户是否有权限可以访问当前的url,当我们的请求量很大时,它对我们数据库的请求量也是非常大的,这时,我们就会想到对我们的权限进行缓存,
这里就讲一下权限的缓存如何进行,
这里使用的是redis
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 引用配置文件 --><context:property-placeholder location="classpath:redis.properties" /><!-- 定义连接池 --><bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" /><!-- 这个bean非常重要 --><bean id="shardedJedisPool" class="redis.clients.jedis.ShardedJedisPool" scope="singleton" > <!-- 上面定义的连接池 --><constructor-arg index="0" ref="jedisPoolConfig" /><constructor-arg index="1"><list> <!-- 连接池的信息 读取配置文件 --><bean class="redis.clients.jedis.JedisShardInfo"><constructor-arg name="host" value="${redis.host}"/><constructor-arg name="port" value="${redis.port}"/><constructor-arg name="timeout" value="${redis.timeout}"/></bean></list></constructor-arg></bean></beans>
redis.host=127.0.0.1 redis.port=6379 redis.timeout=3000
**************************************************************************************************************************************
package com.mmall.service;import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedisPool;import javax.annotation.Resource;// 封装一下radis @Service("redisPool")//加注释让spring来管理 @Slf4j public class RedisPool {// 使用刚刚定义的spring管理的类radis@Resource(name = "shardedJedisPool")//直接调用radis了 单例的servieceprivate ShardedJedisPool shardedJedisPool;//返回单例的实例public ShardedJedis instance() {return shardedJedisPool.getResource();}//安全关闭的方法public void safeClose(ShardedJedis shardedJedis) {try {if (shardedJedis != null) {shardedJedis.close();}} catch (Exception e) {log.error("return redis resource exception", e);}} }
********************************************************************************************************************************
package com.mmall.service;import com.google.common.base.Joiner; import com.mmall.beans.CacheKeyConstants; import com.mmall.util.JsonMapper; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import redis.clients.jedis.ShardedJedis;import javax.annotation.Resource;@Service @Slf4j public class SysCacheService {//引用刚定义的reaispool@Resource(name = "redisPool")private RedisPool redisPool;/**** @param toSavedValue 要保存的值* @param timeoutSeconds 要保存多少秒* @param prefix 前缀 自定义*/public void saveCache(String toSavedValue, int timeoutSeconds, CacheKeyConstants prefix) {//调用下面的方法saveCache(toSavedValue, timeoutSeconds, prefix, null);}//保存cachepublic void saveCache(String toSavedValue, int timeoutSeconds, CacheKeyConstants prefix, String... keys) {if (toSavedValue == null) {return;}ShardedJedis shardedJedis = null;//网络连接可能会有问题 try catchtry {//1.生成对应的keyString cacheKey = generateCacheKey(prefix, keys);//拼接key 系统所有权限大家一样 但是单个用户权限大家不一样//2.拿到资源shardedJedis = redisPool.instance();//单例获取redis//提供好的方法处理 一定要写radis 的apishardedJedis.setex(cacheKey, timeoutSeconds, toSavedValue);} catch (Exception e) {log.error("save cache exception, prefix:{}, keys:{}", prefix.name(), JsonMapper.obj2String(keys), e);} finally {//别忘了释放radisredisPool.safeClose(shardedJedis);}}//获取cache// 参数 前缀 keypublic String getFromCache(CacheKeyConstants prefix, String... keys) {ShardedJedis shardedJedis = null;String cacheKey = generateCacheKey(prefix, keys);//拼接key 系统所有权限大家一样 但是单个用户权限大家不一样try {shardedJedis = redisPool.instance();//单例获取redisString value = shardedJedis.get(cacheKey);//获取值return value;//返回值} catch (Exception e) {log.error("get from cache exception, prefix:{}, keys:{}", prefix.name(), JsonMapper.obj2String(keys), e);return null;} finally {//别忘了释放radisredisPool.safeClose(shardedJedis);}}private String generateCacheKey(CacheKeyConstants prefix, String... keys) {String key = prefix.name();//多个string可以进行拼接if (keys != null && keys.length > 0) {key += "_" + Joiner.on("_").join(keys);}return key;} }
package com.mmall.beans;import lombok.Getter;@Getter public enum CacheKeyConstants {SYSTEM_ACLS,//缓存系统内的所有权限USER_ACLS;//缓存用户的权限}
********************************************************************************************************************************
//从缓存中获取数据public List<SysAcl> getCurrentUserAclListFromCache() {//userIdint userId = RequestHolder.getCurrentUser().getId();//通过key获取valueString cacheValue = sysCacheService.getFromCache(CacheKeyConstants.USER_ACLS, String.valueOf(userId));if (StringUtils.isBlank(cacheValue)) {//为空说明出问题了 重新获取一次List<SysAcl> aclList = getCurrentUserAclList();if (CollectionUtils.isNotEmpty(aclList)) {//重新保存 value 600s有效期 key的值(前缀和userid)sysCacheService.saveCache(JsonMapper.obj2String(aclList), 600, CacheKeyConstants.USER_ACLS, String.valueOf(userId));}return aclList;//没从cache中获取到值从数据库取出来}//缓存中有return JsonMapper.string2Obj(cacheValue, new TypeReference<List<SysAcl>>() {});} }
********************************************************************************************************************************
不是每个方法都要缓存的
有些必须是实时数据不就不能进行缓存
不需要进行特别多的数据访问 就不要缓存
********************************************************************************************************************************
********************************************************************************************************************************
********************************************************************************************************************************
********************************************************************************************************************************
********************************************************************************************************************************
********************************************************************************************************************************