专业的编程技术博客社区

网站首页 > 博客文章 正文

J2Cache实现二级分布式session(分布式二级缓存)

baijin 2024-08-21 11:25:11 博客文章 6 ℃ 0 评论

分布式session实现

分布式session大家都比较熟悉了,一般的实现方式有几种。

  • 容器级别分布式session的实现

最常见容器级别的比如tomcat-redis,tomcat-memcache系列。这种实现方式的好处就是屏蔽了分布式session的细节,做到了对开发人员无感知。

  • https://www.oschina.net/p/tomcat-redis-session-manager
  • https://www.oschina.net/p/memcached-session-manager

但是随着springboot和docker技术的发展嵌入式容器变成大势所趋,这种方式就不太适合。

  • 利用统一存储

一般的架构方案都会考虑把session独立存储在redis或者memcache种。每次使用到session的时候就从redis里面get一次。

优化一点的方案会增加个threadlocal变量,贯穿整个请求,保证一次完整的请求内不在重复从redis里面获取数据session数据。这种方案在请求结束时候的一定记得清空threadlocal变量,不然会引起下次请求的session混乱。

这种方案的缺点是请求量大的时候,由于大量的数据通过缓存获取,导致缓存服务的数据吞吐量太大,带宽容易跑满。当redis出现异常的时候应用会马上无法响应。

二级分布式session实现

利用二级缓存实现分布式session就能完美解决以上问题。

如图所示,应用程序在获取session数据的时候会先从内存中查询,如果没有才会从redis里面获取。

J2Cache是oschina网站实战的产物,它不是一个缓存框架,是一个缓存框架的桥梁。它利用现有优秀的内存缓存框架作为一级缓存,而把 Redis 作为二级缓存。

虽然他支持的一级缓存实现不少,我在这里选择Caffeine作为一级缓存,redis为二级缓存进行演示。

引入J2Cache

<dependency>

<groupId>net.oschina.j2cache</groupId>

<artifactId>j2cache-core</artifactId>

<version>2.7.8-release</version>

</dependency>

配置一级缓存

caffeine.properties

增加一行配置session=1000, 30m 配置缓存实效时间为30分钟也就是session的实效时间

配置二级缓存

j2cache.properties 配置一级缓存二级缓存的提供方式

j2cache.broadcast = redis
j2cache.L1.provider_class = caffeine
j2cache.L2.provider_class = redis

j2cache.properties中配置redis连接地址

redis.hosts = 127.0.0.1
redis.timeout = 2000
redis.password = 
redis.database = 0 redis的index

J2CacheKit 简单封装下

public class J2CacheKit {
	
	private static CacheChannel cache;
	static void init(CacheChannel cache) {
		J2CacheKit.cache = cache;
	}
	
	public static CacheChannel getCacheChannel(){
		return cache;
	}
	@SuppressWarnings("unchecked")
	public static <T> T get(String cacheName, Object key) {
		try {
			CacheObject cacheObject = cache.get(cacheName, key.toString());
			return cacheObject != null ? (T) cacheObject.getValue() : null;
		} catch (Exception e) {
			LogKit.error(e.toString(), e);
		}
		return null;
	}
	public static void put(String cacheName, Object key, Object value) {
		try {
			cache.set(cacheName, key.toString(), (Serializable) value);
		} catch (Exception e) {
			LogKit.error(e.toString(), e);
		}
	}
	public static void remove(String cacheName, String... keys) {
		try {
			cache.evict(cacheName, keys);
		} catch (Exception e) {
			LogKit.error(e.toString(), e);
		}
	}
	public static void removeAll(String cacheName) {
		try {
			cache.clear(cacheName);
		} catch (Exception e) {
			LogKit.error(e.toString(), e);
		}
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T get(String cacheName, Object key, IDataLoader dataLoader) {
		Object value = get(cacheName, key);
		if (value == null) {
			value = dataLoader.load();
			if (value != null) {
				put(cacheName, key, value);
			}
		}
		return (T) value;
	}
	
	public static Collection<String> getKeys(String cacheName) {
		try {
			Collection<String> keys = cache.keys(cacheName);
			return keys == null ? new ArrayList<String>(keys) : null;
		} catch (Exception e) {
			LogKit.error(e.toString(), e);
		}
		return null;
	}
}

当然作者也提供了更佳的完整的模块实现

代码地址如下,有兴趣可以参考下

https://gitee.com/ld/J2Cache/tree/master/modules/session-manager

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表