Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
D
dankal-share-cache
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
仲光辉
dankal-share-cache
Commits
612a46be
Commit
612a46be
authored
Mar 27, 2021
by
仲光辉
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: add customer annotation cache reference.
parent
d2d81138
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
444 additions
and
3 deletions
+444
-3
README.md
README.md
+6
-2
CacheCondition.java
...cn/dankal/share/cache/reference/cache/CacheCondition.java
+52
-0
ObjectCacheKey.java
...cn/dankal/share/cache/reference/cache/ObjectCacheKey.java
+49
-0
ObjectDistributeLockKey.java
.../share/cache/reference/cache/ObjectDistributeLockKey.java
+47
-0
RedisCache.java
...ava/cn/dankal/share/cache/reference/cache/RedisCache.java
+207
-0
RedisCacheAspect.java
.../dankal/share/cache/reference/cache/RedisCacheAspect.java
+0
-0
RedissonBaseConfig.java
...nkal/share/cache/reference/config/RedissonBaseConfig.java
+82
-0
IProvincesServiceImpl.java
...ankal/share/cache/service/impl/IProvincesServiceImpl.java
+1
-1
No files found.
README.md
View file @
612a46be
...
...
@@ -102,7 +102,7 @@ cache: `redis`
}.
getType
());
}
else
{
// 数据没有缓存
// TODO 缓存击穿 分布式锁 etc. Redisson
// TODO 缓存击穿 分布式锁 etc. Redisson
可以参阅 cn.dankal.share.cache.reference
Provinces
provinces
=
this
.
getProvincesByProvinces
(
provincesId
);
Optional
<
Provinces
>
provincesOptional
;
if
(
BeanUtil
.
isNotEmpty
(
provinces
))
{
...
...
@@ -276,6 +276,10 @@ url: GET http://localhost:9102/test/440000
#### 小示例
##### 第三方依赖
> [hutool-bloomFilter](https://mvnrepository.com/artifact/cn.hutool/hutool-bloomFilter)
##### 数据初始化
```
java
...
...
@@ -310,7 +314,7 @@ url: GET http://localhost:9102/test/440000
##### 小提示
> 示例 只是单纯的对 `BitMapBloomFilter`进行初数化,我们还需考虑其数据更新.我们可以在 Provinces进行增删的时候手动对 BitMapBloomFilter`进行更新。当然我们也可以通过订阅 诸如`TiDB`的`Ticdc`来实现`BitMapBloomFilter`的数据更新
> 示例 只是单纯的对 `BitMapBloomFilter`进行初数化,我们还需考虑其数据更新.我们可以在 Provinces进行增删的时候手动对
`
BitMapBloomFilter`进行更新。当然我们也可以通过订阅 诸如`TiDB`的`Ticdc`来实现`BitMapBloomFilter`的数据更新
### 解决方案示例
...
...
src/main/java/cn/dankal/share/cache/reference/cache/CacheCondition.java
0 → 100644
View file @
612a46be
package
cn
.
dankal
.
share
.
cache
.
reference
.
cache
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
java.lang.reflect.Field
;
/**
* 条件缓存
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2021-03-19
*/
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
CacheCondition
{
/**
* Object条件 class
* <pre>
* 如果条件是基本数据类型,则直接顺序指定 {@link #conditionsValues()} 即可
* </pre>
*/
Class
<?>
objectConditionClass
()
default
Object
.
class
;
/**
* 条件对象所在方法参数的索引
*
*/
int
objectConditionParameterIndex
()
default
0
;
/**
* 条件 属性名称 {@link Field#getName()}
* <pre>
* 元素顺序需要和 {@link #conditionsValues()} 保持一致
* 如果条件是基本数据类型,则直接顺序指定 {@link #conditionsValues()} 即可
* </pre>
*/
String
[]
conditionsFieldNames
()
default
{};
/**
* 条件属性值 {@link Field#get(Object)}
* <pre>
* 当使用 {@link #objectConditionClass()} 时 元素顺序需要和 {@link #conditionsFieldNames()} 保持一致
* 如果是基本数据类型,则只需要和方法参数保持一致即可.
* </pre>
*/
String
[]
conditionsValues
();
}
src/main/java/cn/dankal/share/cache/reference/cache/ObjectCacheKey.java
0 → 100644
View file @
612a46be
package
cn
.
dankal
.
share
.
cache
.
reference
.
cache
;
import
cn.hutool.core.util.StrUtil
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* 对象缓存key: 缓存key 的构成需要从对象中获取时,使用当前注解
* 此注解的对于指定 key 的优先级高于 {@link RedisCache#cacheKey()} {@link RedisCache#dynamicCacheKeyPattern()}
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2021-03-19
*/
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
ObjectCacheKey
{
/**
* 对象 类型
*/
Class
<?>
objectClass
();
/**
* 对象所在参数索引
*/
int
objectParameterIndex
()
default
0
;
/**
* 动态缓存 key pattern
* <pre>
* 动态 缓存 key pattern {@link StrUtil#format(CharSequence, Object...)}
* 占位符顺序需要和 {@link #fieldNames()} 一致
* </pre>
*/
String
dynamicCacheKeyPattern
();
/**
* 参与动态缓存 key 构成的属性名称
* <pre>
* 顺序需要和 {@link #dynamicCacheKeyPattern()} 保持一致
* </pre>
*/
String
[]
fieldNames
();
}
src/main/java/cn/dankal/share/cache/reference/cache/ObjectDistributeLockKey.java
0 → 100644
View file @
612a46be
package
cn
.
dankal
.
share
.
cache
.
reference
.
cache
;
import
cn.hutool.core.util.StrUtil
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
/**
* ObjectDistributeLockKey 分布式锁动态key: pattern value 从对象中获取
* 此注解的对于指定 key 的优先级高于 {@link RedisCache#distributedLockKey()} ()} {@link RedisCache#dynamicDistributedLockKeyPattern()}
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2021/03/21
*/
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
ObjectDistributeLockKey
{
/**
* 对象 类型
*/
Class
<?>
objectClass
();
/**
* 对象所在参数索引
*/
int
objectParameterIndex
()
default
0
;
/**
* 动态缓存 key pattern
* <pre>
* 动态 缓存 key pattern {@link StrUtil#format(CharSequence, Object...)}
* 占位符顺序需要和 {@link #fieldNames()} 一致
* </pre>
*/
String
dynamicDistributeLockKeyPattern
();
/**
* 参与动态缓存 key 构成的属性名称
* <pre>
* 顺序需要和 {@link #dynamicDistributeLockKeyPattern()} 保持一致
* </pre>
*/
String
[]
fieldNames
();
}
src/main/java/cn/dankal/share/cache/reference/cache/RedisCache.java
0 → 100644
View file @
612a46be
package
cn
.
dankal
.
share
.
cache
.
reference
.
cache
;
import
java.lang.annotation.ElementType
;
import
java.lang.annotation.Retention
;
import
java.lang.annotation.RetentionPolicy
;
import
java.lang.annotation.Target
;
import
java.util.concurrent.TimeUnit
;
/**
* redis 缓存注解
* <p>
* 在需要使用 redis 缓存的 方法上 使用 当前注解
* </p>
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2021-02-26
* @see RedisCacheAspect
*/
@Target
(
ElementType
.
METHOD
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
@interface
RedisCache
{
/**
* 缓存 key
* <p>
* dynamicCacheKey=false 时,直接使用 cacheKey 作为缓存可以
* </p>
*
* @return 缓存 key
*/
String
cacheKey
()
default
""
;
/**
* 是否使用 动态 缓存key
* <p>
* etc. product_item_13245253625232
* </p>
*
* @return 是否使用 动态 缓存key
*/
boolean
dynamicCacheKey
()
default
true
;
/**
* 动态 缓存 key pattern etc. "product_item_{}"
* <pre>
* dynamicCacheKey=true
* 具体请参阅
* cn.hutool.core.util.StrUtil#format(java.lang.CharSequence, java.lang.Object...)
* </pre>
*
* @return 动态 缓存 key pattern etc. "product_item_{}"
*/
String
dynamicCacheKeyPattern
()
default
""
;
/**
* 动态缓存 key 动态值所在方法参数的位置索引
* <pre>
* {@code
* dynamicCacheKey=true
* etc.
*
* dynamicCacheKeyParameterIndexArray = {0}
* dynamicCacheKeyPattern=product_item_{}
*
* public Product getProduct(Integer productId,...){
* ... ...
* }
*
* getProduct(1324536795953)
* the full cache key : product_item_1324536795953
* }
* </pre>
*
* @return 动态缓存 key 动态值所在方法参数的位置索引
*/
int
[]
dynamicCacheKeyParameterIndexArray
()
default
{
0
};
/**
* 缓存 过期时间
* <p>
* 如果 cacheTimeout 小于等于0 则表示缓存属于永久缓存
* <br/>
* 当且仅当 cacheTimeout 的值 大于 0 时 当前配置才生效
* </p>
*
* @return 缓存 过期时间
*/
long
cacheTimeout
()
default
0
;
/**
* 缓存过期时间单位
*
* @return 缓存过期时间单位
*/
TimeUnit
cacheTimeoutUnit
()
default
TimeUnit
.
MINUTES
;
/**
* 为了避免缓存穿透,我们需要对空值进行缓存
* 空值缓存 过期时间 (单位: 分钟)
*
* @return 空值缓存 过期时间
*/
long
emptyObjectCacheTimeout
()
default
5
;
/**
* 是否使用分布式锁
*
* @return 是否使用分布式锁
*/
boolean
useDistributeLock
()
default
true
;
/**
* 分布式锁 key
* <p>
* 当且仅当 <code>useDistributeLock=true</code>时,当前配置才会生效(使用)
* <br/>
* distributedLockKey 不能为空
* </p>
*
* @return 分布式锁 key
*/
String
distributedLockKey
()
default
""
;
/**
* 是否使用 动态 distributedLockKey
* <pre>
* distributedLockKey=false
* 直接使用 distributedLockKey 作为 分布式锁 的 key
*
* distributedLockKey=true
* dynamicDistributedLockKeyPattern 和 dynamicDistributedLockKeyParameterIndexArray 动态生成分布式锁 的 key
* </pre>
*
* @return boolean
*/
boolean
dynamicDistributedLockKey
()
default
true
;
/**
* 动态 分布式锁 key pattern etc. "product_item_{}"
* <pre>
* dynamicDistributedLockKey=true
* cn.hutool.core.util.StrUtil#format(java.lang.CharSequence, java.lang.Object...)
* </pre>
*
* @return 动态 分布式锁 key pattern etc. "product_item_{}"
*/
String
dynamicDistributedLockKeyPattern
()
default
""
;
/**
* 动态分布式锁 key 动态值所在方法参数的位置索引 数组
* <pre>
* <text>
* dynamicDistributedLockKey=true
* etc.
* dynamicDistributedLockKeyParameterIndexArray ={0}
* dynamicDistributedLockKeyPattern=product_item_{}
* {@code
* public Product getProduct(Integer productId,...){
* ... ...
* }
* }
* getProduct(1324536795953)
* the full distributed lock key : product_item_1324536795953
* </text>
* </pre>
*
* @return 动态分布式锁 key 动态值所在方法参数的位置索引 数组
*/
int
[]
dynamicDistributedLockKeyParameterIndexArray
()
default
{
0
};
/**
* 尝试获取 redisson lock 等待的时间
* <p>
* 当且仅当 <code>isUseDistributeLock=true</code>时,当前配置才会生效(使用)
* <br/>
* 此值只用于避免 redis 服务器网络延迟,不易设置过大 切切
* </p>
*
* @return 尝试获取 redisson lock 等待的时间
*/
long
redissonTryLockWaitTime
()
default
120
;
/**
* 持有 redisson lock 的时间
* <p>
* 当且仅当 <code>isUseDistributeLock=true</code>时,当前配置才会生效(使用)
* </p>
*
* @return 持有 redisson lock 的时间
*/
long
redissonLockLeaseTime
()
default
230
;
/**
* redisson lock 时间单位
* <p>
* <text>
* redissonTryLockWaitTime
* redissonLockLeaseTime
* </text>
* </p>
*
* @return redisson lock 时间单位
*/
TimeUnit
redissonLockTimeunit
()
default
TimeUnit
.
MILLISECONDS
;
}
src/main/java/cn/dankal/share/cache/reference/cache/RedisCacheAspect.java
0 → 100644
View file @
612a46be
This diff is collapsed.
Click to expand it.
src/main/java/cn/dankal/share/cache/reference/config/RedissonBaseConfig.java
0 → 100644
View file @
612a46be
package
cn
.
dankal
.
share
.
cache
.
reference
.
config
;
import
cn.hutool.core.util.StrUtil
;
import
org.redisson.Redisson
;
import
org.redisson.api.RedissonClient
;
import
org.redisson.config.Config
;
import
org.springframework.boot.autoconfigure.data.redis.RedisProperties
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.util.CollectionUtils
;
import
java.util.List
;
/**
* RedissonBaseConfig
* <br/>
*
* @author ZGH.MercyModest
* @version V1.0.0
* @create 2021/02/26
* @copyright 蛋壳创意科技 - www.dankal.cn
*/
@Configuration
public
class
RedissonBaseConfig
{
/**
* RedisProperties
*/
private
final
RedisProperties
redisProperties
;
/**
* redisson redis host prefix
*/
private
final
static
String
ADDRESS_PREFIX
=
"redis://"
;
public
RedissonBaseConfig
(
RedisProperties
redisProperties
)
{
this
.
redisProperties
=
redisProperties
;
}
@Bean
(
destroyMethod
=
"shutdown"
)
public
RedissonClient
redissonClient
()
{
Config
config
=
new
Config
();
// 验证是否配置了 redis host/ redis nodes
String
redisHost
=
redisProperties
.
getHost
();
RedisProperties
.
Cluster
propertiesCluster
=
redisProperties
.
getCluster
();
boolean
checkRedisHost
=
StrUtil
.
isBlank
(
redisHost
)
&&
(
propertiesCluster
==
null
||
CollectionUtils
.
isEmpty
(
propertiesCluster
.
getNodes
()));
if
(
checkRedisHost
)
{
throw
new
IllegalArgumentException
(
"需要配置 redis.host 或 redis.cluster.nodes"
);
}
if
(
null
!=
propertiesCluster
&&
!
CollectionUtils
.
isEmpty
(
propertiesCluster
.
getNodes
()))
{
// redis cluster
config
.
useClusterServers
()
.
addNodeAddress
(
this
.
transferRedissonRedisNode
(
propertiesCluster
.
getNodes
()))
.
setPassword
(
redisProperties
.
getPassword
())
.
setTimeout
((
int
)
redisProperties
.
getTimeout
().
toMillis
());
}
else
{
// redis singleton
config
.
useSingleServer
()
.
setAddress
(
ADDRESS_PREFIX
+
redisHost
+
":"
+
redisProperties
.
getPort
())
.
setTimeout
((
int
)
redisProperties
.
getTimeout
().
toMillis
())
.
setPassword
(
redisProperties
.
getPassword
());
}
return
Redisson
.
create
(
config
);
}
/**
* 将 node list 转化为 redisson redis cluster config
* <p>
* 127.0.0.0:6379 --> redis://127.0.0.1:6379
* </p>
*
* @param redisNodeList redisNodeList
* @return string []
*/
private
String
[]
transferRedissonRedisNode
(
List
<
String
>
redisNodeList
)
{
String
[]
resultArray
=
new
String
[
redisNodeList
.
size
()];
for
(
int
i
=
0
;
i
<
resultArray
.
length
;
i
++)
{
resultArray
[
i
]
=
ADDRESS_PREFIX
+
redisNodeList
.
get
(
i
);
}
return
resultArray
;
}
}
src/main/java/cn/dankal/share/cache/service/impl/IProvincesServiceImpl.java
View file @
612a46be
...
...
@@ -108,7 +108,7 @@ public class IProvincesServiceImpl extends ServiceImpl<ProvincesMapper, Province
}.
getType
());
}
else
{
// 数据没有缓存
// TODO 缓存击穿 分布式锁 etc. Redisson
// TODO 缓存击穿 分布式锁 etc. Redisson
可以参阅 cn.dankal.share.cache.reference
Provinces
provinces
=
this
.
getProvincesByProvinces
(
provincesId
);
Optional
<
Provinces
>
provincesOptional
;
if
(
BeanUtil
.
isNotEmpty
(
provinces
))
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment