Spring Boot缓存------基于ConcurrentHashMap和Redis的两级缓存管理

Spring Boot项目缓存配置(未测试,未完善)

1、你需要准备和配置的事情

引入依赖

<!-- Redis数据库 -->
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

基础配置

#缓存策略相关配置
spring.cache.type=REDIS
spring.cache.redis.time-to-live=600000
#Redis缓存数据库配置
spring.redis.host=127.0.0.1
spring.redis.port=6379
spring.redis.password=
spring.redis.jedis.pool.max-active=8
#这个是自定义的标识,用于指定Redis的消息通道名
springext.cache.redis.channel=cache

2、基于ConcurrentHashMap和Redis的两级缓存管理器

package com.drsanjun.cache;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCache;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * 基于ConcurrentHashMap和Redis的两级缓存管理器
 * 
 * @author dyw
 * @date 2019年9月30日
 */
@SuppressWarnings("rawtypes")
public class TwoLevelCacheManager extends RedisCacheManager {
	@Value("springext.cache.redis.channel")
	private String topicName;
	/**
	 * Redis缓存数据库访问工具
	 */
	private RedisTemplate redisTemplate;

	/**
	 * 
	 * @param redisTemplate
	 * @param cacheWriter
	 * @param defaultCacheConfiguration
	 */
	public TwoLevelCacheManager(RedisTemplate redisTemplate, RedisCacheWriter cacheWriter,
			RedisCacheConfiguration defaultCacheConfiguration) {
		super(cacheWriter, defaultCacheConfiguration);
		this.redisTemplate = redisTemplate;
	}

	@Override
	protected Cache decorateCache(Cache cache) {
		return new RedisAndLocalCache(this, (RedisCache) cache);
	}

	/**
	 * 
	 * @param channel
	 * @param cacheName
	 */
	public void publishMessage(String cacheName) {
		this.redisTemplate.convertAndSend(topicName, cacheName);

	}

	/**
	 * 
	 * @param name
	 */
	public void receiver(String name) {
		RedisAndLocalCache cache = (RedisAndLocalCache) this.getCache(name);
		if (cache != null) {
			cache.clearLocal();
		}
	}
}

3、基于ConcurrentHashMap和Redis的两级缓存器

package com.drsanjun.cache;

import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.cache.Cache;
import org.springframework.data.redis.cache.RedisCache;

/**
 * 基于ConcurrentHashMap和Redis的两级缓存器
 * 
 * @author dyw
 * @date 2019年9月30日
 */
public class RedisAndLocalCache implements Cache {
	private ConcurrentHashMap<Object, Object> local = new ConcurrentHashMap<>();
	private RedisCache redisCache;
	private TwoLevelCacheManager cacheManager;

	public RedisAndLocalCache(TwoLevelCacheManager redisCacheManager, RedisCache cache) {
		this.redisCache = cache;
		this.cacheManager = redisCacheManager;
	}

	@Override
	public String getName() {
		return redisCache.getName();
	}

	@Override
	public Object getNativeCache() {
		return redisCache.getNativeCache();
	}

	@Override
	public ValueWrapper get(Object key) {
		ValueWrapper wrapper = (ValueWrapper) local.get(key);
		if (wrapper == null) {
			return wrapper;
		} else {
			wrapper = redisCache.get(key);
			if (wrapper != null) {
				local.put(key, wrapper);
			}
			return wrapper;
		}
	}

	@Override
	public void put(Object key, Object value) {
		redisCache.put(key, value);
		clearOtherJVM();
	}

	@Override
	public void evict(Object key) {
		redisCache.evict(key);
		clearOtherJVM();
	}

	@Override
	public <T> T get(Object key, Class<T> type) {
		return redisCache.get(key, type);
	}

	@Override
	public <T> T get(Object key, Callable<T> valueLoader) {
		return redisCache.get(key, valueLoader);
	}

	@Override
	public ValueWrapper putIfAbsent(Object key, Object value) {
		return redisCache.putIfAbsent(key, value);
	}

	@Override
	public void clear() {
		redisCache.clear();
	}

	protected void clearOtherJVM() {
		cacheManager.publishMessage(redisCache.getName());
	}

	public void clearLocal() {
		this.local.clear();
	}
}

4、缓存配置

package com.drsanjun.configuration;

import java.io.UnsupportedEncodingException;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair;

import com.drsanjun.cache.TwoLevelCacheManager;

/**
 * 缓存配置
 * 
 * @author dyw
 * @date 2019年9月30日
 */
@Configuration
@SuppressWarnings("rawtypes")
public class CacheConfig {
	@Value("springext.cache.redis.channel")
	private String topicName;

	public TwoLevelCacheManager cacheManager(StringRedisTemplate redisTemplate) {
		RedisCacheWriter writer = RedisCacheWriter.lockingRedisCacheWriter(redisTemplate.getConnectionFactory());
		SerializationPair pair = SerializationPair
				.fromSerializer(new JdkSerializationRedisSerializer(this.getClass().getClassLoader()));
		RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
		return new TwoLevelCacheManager(redisTemplate, writer, config);
	}

	@Bean
	RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
			MessageListenerAdapter listenerAdapter) {
		RedisMessageListenerContainer container = new RedisMessageListenerContainer();
		container.setConnectionFactory(connectionFactory);
		container.addMessageListener(listenerAdapter, new PatternTopic(topicName));
		return container;
	}

	@Bean
	MessageListenerAdapter listenerAdapter(final TwoLevelCacheManager cacheManager) {
		return new MessageListenerAdapter(new MessageListener() {
			@Override
			public void onMessage(Message message, byte[] pattern) {
				try {
					String cacheName = new String(message.getBody(), "UTF-8");
					cacheManager.receiver(cacheName);
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
		});
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

豢龙先生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值