Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
提交反馈
为 GitLab 提交贡献
登录
切换导航
I
ibzwf
项目
项目
详情
动态
版本
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
ibiz4jteam
ibzwf
提交
a08ca6f5
提交
a08ca6f5
编写于
6月 02, 2020
作者:
ibizdev
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
zhouweidong@lab.ibiz5.com 发布系统代码
上级
80c78419
变更
2
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
2 行增加
和
370 行删除
+2
-370
LayeringCache.java
...in/java/cn/ibizlab/util/cache/layering/LayeringCache.java
+1
-193
LayeringCacheManager.java
.../cn/ibizlab/util/cache/layering/LayeringCacheManager.java
+1
-177
未找到文件。
ibzwf-util/src/main/java/cn/ibizlab/util/cache/layering/LayeringCache.java
浏览文件 @
a08ca6f5
package
cn
.
ibizlab
.
util
.
cache
.
layering
;
import
cn.ibizlab.util.enums.RedisChannelTopic
;
import
cn.ibizlab.util.cache.listener.RedisPublisher
;
import
cn.ibizlab.util.cache.redis.CustomizedRedisCache
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.cache.caffeine.CaffeineCache
;
import
org.springframework.cache.support.AbstractValueAdaptingCache
;
import
org.springframework.cache.support.NullValue
;
import
org.springframework.data.redis.cache.RedisCache
;
import
org.springframework.data.redis.cache.RedisCacheConfiguration
;
import
org.springframework.data.redis.cache.RedisCacheWriter
;
import
org.springframework.data.redis.core.RedisOperations
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.concurrent.Callable
;
/**
* 缓存分层类
* 1级缓存为caffeine
* 2级缓存为redis
*/
public
class
LayeringCache
extends
AbstractValueAdaptingCache
{
Logger
logger
=
LoggerFactory
.
getLogger
(
LayeringCache
.
class
);
public
class
LayeringCache
{
/**
* 缓存的名称
*/
private
final
String
name
;
/**
* 是否使用一级缓存
*/
private
boolean
usedFirstCache
=
true
;
/**
* redi缓存
*/
private
RedisCache
redisCache
;
/**
* Caffeine缓存
*/
private
final
CaffeineCache
caffeineCache
;
RedisOperations
<?
extends
Object
,
?
extends
Object
>
redisOperations
;
/**
* @param name 缓存名称
* @param allowNullValues 是否允许存NULL,默认是false
* @param usedFirstCache 是否使用一级缓存,默认是true
* @param caffeineCache Caffeine缓存
*/
public
LayeringCache
(
String
name
,
boolean
allowNullValues
,
RedisOperations
redisOperations
,
boolean
usedFirstCache
,
com
.
github
.
benmanes
.
caffeine
.
cache
.
Cache
<
Object
,
Object
>
caffeineCache
,
RedisCacheWriter
redisCacheWriter
,
RedisCacheConfiguration
configuration
)
{
super
(
allowNullValues
);
this
.
name
=
name
;
this
.
usedFirstCache
=
usedFirstCache
;
this
.
redisCache
=
new
CustomizedRedisCache
(
name
,
redisCacheWriter
,
configuration
);
this
.
caffeineCache
=
new
CaffeineCache
(
name
,
caffeineCache
,
allowNullValues
);
this
.
redisOperations
=
redisOperations
;
}
public
CaffeineCache
getFirstCache
()
{
return
this
.
caffeineCache
;
}
@Override
public
String
getName
()
{
return
this
.
name
;
}
@Override
public
Object
getNativeCache
()
{
return
this
;
}
@Override
public
ValueWrapper
get
(
Object
key
)
{
ValueWrapper
wrapper
=
null
;
if
(
usedFirstCache
)
{
// 查询一级缓存
wrapper
=
caffeineCache
.
get
(
key
);
logger
.
debug
(
"查询一级缓存 key:{},value:{}"
,
key
,
wrapper
);
}
if
(
wrapper
==
null
)
{
// 查询二级缓存
wrapper
=
redisCache
.
get
(
key
);
caffeineCache
.
put
(
key
,
wrapper
==
null
?
null
:
wrapper
.
get
());
logger
.
debug
(
"查询二级缓存,并将数据放到一级缓存。 key:{}"
,
key
);
}
return
wrapper
;
}
@Override
public
<
T
>
T
get
(
Object
key
,
Class
<
T
>
type
)
{
T
value
=
null
;
if
(
usedFirstCache
)
{
// 查询一级缓存
value
=
caffeineCache
.
get
(
key
,
type
);
logger
.
debug
(
"查询一级缓存 key:{}"
,
key
);
}
if
(
value
==
null
)
{
// 查询二级缓存
value
=
redisCache
.
get
(
key
,
type
);
caffeineCache
.
put
(
key
,
value
);
logger
.
debug
(
"查询二级缓存,并将数据放到一级缓存。 key:{}"
,
key
);
}
return
value
;
}
@SuppressWarnings
(
"unchecked"
)
@Override
public
<
T
>
T
get
(
Object
key
,
Callable
<
T
>
valueLoader
)
{
T
value
=
null
;
if
(
usedFirstCache
)
{
// 查询一级缓存,如果一级缓存没有值则调用getForSecondaryCache(k, valueLoader)查询二级缓存
value
=
(
T
)
caffeineCache
.
getNativeCache
().
get
(
key
,
k
->
getForSecondaryCache
(
k
,
valueLoader
));
}
else
{
// 直接查询二级缓存
value
=
(
T
)
getForSecondaryCache
(
key
,
valueLoader
);
}
if
(
value
instanceof
NullValue
)
{
return
null
;
}
return
value
;
}
@Override
public
void
put
(
Object
key
,
Object
value
)
{
if
(
usedFirstCache
)
{
caffeineCache
.
put
(
key
,
value
);
}
redisCache
.
put
(
key
,
value
);
}
@Override
public
ValueWrapper
putIfAbsent
(
Object
key
,
Object
value
)
{
if
(
usedFirstCache
)
{
caffeineCache
.
putIfAbsent
(
key
,
value
);
}
return
redisCache
.
putIfAbsent
(
key
,
value
);
}
@Override
public
void
evict
(
Object
key
)
{
redisCache
.
evict
(
key
);
//清除redis中的二级缓存
if
(
usedFirstCache
)
{
caffeineCache
.
evict
(
key
);
//清除本机一级缓存
Map
<
String
,
Object
>
message
=
new
HashMap
<>();
message
.
put
(
"cacheName"
,
name
);
message
.
put
(
"key"
,
key
);
RedisPublisher
redisPublisher
=
new
RedisPublisher
(
redisOperations
,
RedisChannelTopic
.
REDIS_CACHE_DELETE_TOPIC
.
getChannelTopic
());
// 创建redis发布者
redisPublisher
.
publisher
(
message
);
//发布消息,清除其它集群机器中的一级缓存
}
logger
.
debug
(
String
.
format
(
"清除二级缓存数据[%s]"
,
key
));
}
@Override
public
void
clear
()
{
redisCache
.
clear
();
//清除redis中的二级缓存
if
(
usedFirstCache
)
{
caffeineCache
.
clear
();
//清除本机一级缓存
Map
<
String
,
Object
>
message
=
new
HashMap
<>();
message
.
put
(
"cacheName"
,
name
);
RedisPublisher
redisPublisher
=
new
RedisPublisher
(
redisOperations
,
RedisChannelTopic
.
REDIS_CACHE_CLEAR_TOPIC
.
getChannelTopic
());
// 创建redis发布者
redisPublisher
.
publisher
(
message
);
//发布消息,清除其它集群机器中的一级缓存
}
}
@Override
protected
Object
lookup
(
Object
key
)
{
Object
value
=
null
;
if
(
usedFirstCache
)
{
value
=
caffeineCache
.
get
(
key
);
logger
.
debug
(
"查询一级缓存 key:{}"
,
key
);
}
if
(
value
==
null
)
{
value
=
redisCache
.
get
(
key
);
logger
.
debug
(
"查询二级缓存 key:{}"
,
key
);
}
return
value
;
}
/**
* 查询二级缓存
* @param key
* @param valueLoader
* @return
*/
private
<
T
>
Object
getForSecondaryCache
(
Object
key
,
Callable
<
T
>
valueLoader
)
{
T
value
=
redisCache
.
get
(
key
,
valueLoader
);
logger
.
debug
(
"查询二级缓存 key:{}"
,
key
);
return
toStoreValue
(
value
);
}
}
ibzwf-util/src/main/java/cn/ibizlab/util/cache/layering/LayeringCacheManager.java
浏览文件 @
a08ca6f5
package
cn
.
ibizlab
.
util
.
cache
.
layering
;
import
com.github.benmanes.caffeine.cache.Caffeine
;
import
com.github.benmanes.caffeine.cache.CaffeineSpec
;
import
cn.ibizlab.util.cache.setting.FirstCacheSetting
;
import
cn.ibizlab.util.cache.setting.SecondaryCacheSetting
;
import
lombok.Data
;
import
org.springframework.cache.Cache
;
import
org.springframework.cache.CacheManager
;
import
org.springframework.data.redis.cache.RedisCacheConfiguration
;
import
org.springframework.data.redis.cache.RedisCacheWriter
;
import
org.springframework.data.redis.core.RedisOperations
;
import
org.springframework.data.redis.core.RedisTemplate
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.ObjectUtils
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Map
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentMap
;
import
java.util.concurrent.TimeUnit
;
import
org.springframework.util.StringUtils
;
public
class
LayeringCacheManager
{
/**
* 缓存分层类
* 1级缓存为caffeine
* 2级缓存为redis
*/
@Data
public
class
LayeringCacheManager
implements
CacheManager
{
static
final
int
DEFAULT_EXPIRE_AFTER_WRITE
=
2
;
static
final
int
DEFAULT_INITIAL_CAPACITY
=
5
;
static
final
int
DEFAULT_MAXIMUM_SIZE
=
1_000
;
private
final
ConcurrentMap
<
String
,
Cache
>
cacheMap
=
new
ConcurrentHashMap
<
String
,
Cache
>(
16
);
/**
* 一级缓存配置
*/
private
Map
<
String
,
FirstCacheSetting
>
firstCacheSettings
=
null
;
/**
* 二级缓存配置
*/
private
Map
<
String
,
SecondaryCacheSetting
>
secondaryCacheSettings
=
null
;
public
RedisCacheWriter
redisCacheWriter
;
public
RedisCacheConfiguration
redisConfiguration
;
public
RedisOperations
redisOperations
;
/**
* 是否允许动态创建缓存,默认是true
*/
private
boolean
dynamic
=
true
;
/**
* 缓存值是否允许为NULL
*/
private
boolean
allowNullValues
=
false
;
/**
* expireAfterWrite:2 小时
* initialCapacity:5
* maximumSize: 1_000
*/
private
Caffeine
<
Object
,
Object
>
cacheBuilder
=
Caffeine
.
newBuilder
()
.
expireAfterAccess
(
DEFAULT_EXPIRE_AFTER_WRITE
,
TimeUnit
.
HOURS
)
.
initialCapacity
(
DEFAULT_INITIAL_CAPACITY
)
.
maximumSize
(
DEFAULT_MAXIMUM_SIZE
);
public
LayeringCacheManager
(
RedisTemplate
<
String
,
Object
>
redisTemplate
)
{
this
.
redisOperations
=
redisTemplate
;
}
/**
* 获取缓存对象
* @param name
* @return
*/
@Override
public
Cache
getCache
(
String
name
)
{
Cache
cache
=
this
.
cacheMap
.
get
(
name
);
if
(
cache
==
null
&&
this
.
dynamic
)
{
synchronized
(
this
.
cacheMap
)
{
cache
=
this
.
cacheMap
.
get
(
name
);
if
(
cache
==
null
)
{
cache
=
createCache
(
name
);
this
.
cacheMap
.
put
(
name
,
cache
);
}
}
}
return
cache
;
}
@Override
public
Collection
<
String
>
getCacheNames
()
{
return
Collections
.
unmodifiableSet
(
this
.
cacheMap
.
keySet
());
}
protected
Cache
createCache
(
String
name
)
{
return
new
LayeringCache
(
name
,
isAllowNullValues
(),
this
.
redisOperations
,
getUsedFirstCache
(
name
),
createNativeCaffeineCache
(
name
),
redisCacheWriter
,
redisConfiguration
);
}
/**
* Create a native Caffeine Cache instance for the specified cache name.
*
* @param name the name of the cache
* @return the native Caffeine Cache instance
*/
protected
com
.
github
.
benmanes
.
caffeine
.
cache
.
Cache
<
Object
,
Object
>
createNativeCaffeineCache
(
String
name
)
{
return
getCaffeine
(
name
).
build
();
}
/**
* 使用该CacheManager的当前状态重新创建已知的缓存。
*/
private
void
refreshKnownCaches
()
{
for
(
Map
.
Entry
<
String
,
Cache
>
entry
:
this
.
cacheMap
.
entrySet
())
{
entry
.
setValue
(
createCache
(
entry
.
getKey
()));
}
}
/**
* 设置是否允许Cache的值为null
*
* @param allowNullValues
*/
public
void
setAllowNullValues
(
boolean
allowNullValues
)
{
if
(
this
.
allowNullValues
!=
allowNullValues
)
{
this
.
allowNullValues
=
allowNullValues
;
refreshKnownCaches
();
}
}
/**
* 获取是否允许Cache的值为null
*
* @return
*/
public
boolean
isAllowNullValues
()
{
return
this
.
allowNullValues
;
}
/**
* 根据缓存名称设置一级缓存的有效时间和刷新时间,单位秒
*
* @param firstCacheSettings
*/
public
void
setFirstCacheSettings
(
Map
<
String
,
FirstCacheSetting
>
firstCacheSettings
)
{
this
.
firstCacheSettings
=
(!
CollectionUtils
.
isEmpty
(
firstCacheSettings
)
?
new
ConcurrentHashMap
<>(
firstCacheSettings
)
:
null
);
}
/**
* 获取是否使用一级缓存,默认是true
*/
public
boolean
getUsedFirstCache
(
String
name
)
{
SecondaryCacheSetting
secondaryCacheSetting
=
null
;
if
(!
CollectionUtils
.
isEmpty
(
secondaryCacheSettings
))
{
secondaryCacheSetting
=
secondaryCacheSettings
.
get
(
name
);
}
return
secondaryCacheSetting
!=
null
?
secondaryCacheSetting
.
getUsedFirstCache
()
:
true
;
}
public
void
setCaffeineSpec
(
CaffeineSpec
caffeineSpec
)
{
Caffeine
<
Object
,
Object
>
cacheBuilder
=
Caffeine
.
from
(
caffeineSpec
);
if
(!
ObjectUtils
.
nullSafeEquals
(
this
.
cacheBuilder
,
cacheBuilder
))
{
this
.
cacheBuilder
=
cacheBuilder
;
refreshKnownCaches
();
}
}
private
Caffeine
<
Object
,
Object
>
getCaffeine
(
String
name
)
{
if
(!
CollectionUtils
.
isEmpty
(
firstCacheSettings
))
{
FirstCacheSetting
firstCacheSetting
=
firstCacheSettings
.
get
(
name
);
if
(
firstCacheSetting
!=
null
&&
StringUtils
.
isEmpty
(
firstCacheSetting
.
getCacheSpecification
()))
{
// 根据缓存名称获取一级缓存配置
return
Caffeine
.
from
(
CaffeineSpec
.
parse
(
firstCacheSetting
.
getCacheSpecification
()));
}
}
return
this
.
cacheBuilder
;
}
}
编辑
预览
Markdown
格式
0%
请重试
or
添加新附件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
先完成此消息的编辑!
取消
想要评论请
注册
或
登录