Comments (17)
我觉得这样不好。
对于绝大部分应用来说,area是不需要设置的,除非这个应用需要连接两个不同的redis集群。
不同方法的name一般来说是不应该一样的,而且name也是可选的配置,不设置会自动生成一个。
cacheType默认REMOTE也是较好的设置。
直接把Cached写在class上面有些乱,那些属性是有效的,那些是无意义的,这怎么区分,除非发明一个新注解。
另外配置散落在各个地方是不好的,我想知道一个方法的属性是什么值,先查方法上面的注解,然后再查class上的注解,最后再查yml全局配置,这样是不是太麻烦了?
如果做一个选择:A,简单、重复繁琐。B,复杂,无重复。
那我选A。
from jetcache.
@Cached
支持在class上使用后,可以由开发者决定是否使用,对于之前习惯在method上一一配置的人来说,没有任何改变,并没有要求开发者一定要怎么写的。
对于area,默认是default,对绝大部分应用来说是不需要设置,一旦需要设置,那就每个注解上都要设置,非常麻烦,目前好像没有看到有地方可以统一设置。
项目里生成key的时候,需要拼接area、name和key,用的连接符是_
,这和目前常用的redis key连接符:
不一样,会造成在部分redis管理工具不能对key进行很好的分层,建议是有个配置项对默认连接符进行配置。
关于是否在class上使用@Cached
,举个对比的例子吧。
public class CacheService {
@Cached(area = "book", name = ":activity:byId:", key = "#id", cacheType = CacheType.BOTH, expire = 300)
@CacheRefresh(refresh = 60)
public NutMap getActivity(Long id) {}
@Cached(area = "book", name = ":viewpoints:", key = "#id", cacheType = CacheType.BOTH, expire = 300)
@CacheRefresh(refresh = 10)
public List<NutMap> getViewpoints(Long id) {}
@Cached(area = "book", name = ":rotation:", key = "#id", cacheType = CacheType.BOTH, expire = 300)
@CacheRefresh(refresh = 10)
public List<NutMap> getRotation(Long id) {}
@Cached(area = "book", name = ":viewpoint:", key = "#id + '#activityId'", cacheType = CacheType.BOTH, expire = 300)
@CacheRefresh(refresh = 10)
public NutMap getViewpoint(Long id, Long activityId) { }
}
再看看在class上的
@Cached(area = "book", cacheType = CacheType.BOTH, expire = 300)
@CacheRefresh(refresh = 60)
public class CacheService {
@Cached(name = ":activity:byId:", key = "#id")
public NutMap getActivity(Long id) {}
@Cached(name = ":viewpoints:", key = "#id")
public List<NutMap> getViewpoints(Long id) {}
@Cached(name = ":rotation:", key = "#id")
public List<NutMap> getRotation(Long id) {}
@Cached(name = ":viewpoint:", key = "#id + '#activityId'")
public NutMap getViewpoint(Long id, Long activityId) {}
}
下面的版本明显更清晰,可读性更高啊,当然,就像前面说的,更喜欢单独针对method进行设置的,也可用继续用前一种写法。但是作为一个程序员,看着同一段配置代码被四处copy是一件很别扭的事情。
from jetcache.
项目里生成key的时候,拼接area、name和key的时候,用的连接符是_,这和目前常用的redis key连接符:不一样,会造成在部分redis管理工具不能对key进行很好的分层,建议是有个配置项对默认连接符进行配置。
这个是可以考虑的,不过我要说明一点,area并不拼接为key的一部分,area是用来查找对应的缓存配置的,比如连接到另一个redis集群。
我还是不喜欢太复杂,给人选择太多不一定是好事,容易留坑,而且复杂化以后bug也容易多。
很多时候繁琐而简单的代码可读性高。你的第二个版本,类很短,一眼能看到头,但是实际项目开发中类都很大,那么我读代码的时候,在一个方法上面发现了一个Cached注解,它到底会有什么样的行为,还要翻到文件的最上面去看一下,然后在我的脑子中merge一下,我不认为这样算可读性高。如果不明真相的群众没有到上面去看一下,那么理解错了行为,不就是一个坑吗?增加这个功能不是给了你一个在类上写注解的选择,而是强迫所有用户都要翻到最上面看一下。
其它:
- 你的第一段代码繁琐有一个原因是它设置了name,而第二段代码没有设置。
- 默认expire可以在yml中全局设置。
- 正常情况用默认cacheType = CacheType.REMOTE足够了,除非是访问量特别大的,所有的地方都设置BOTH会占用太多内存。
from jetcache.
项目里生成key的时候,拼接area、name和key的时候,用的连接符是_,这和目前常用的redis key连接符:不一样,会造成在部分redis管理工具不能对key进行很好的分层,建议是有个配置项对默认连接符进行配置。
看了下代码,name和key之间没有下划线连接,而是直接拼接的,如果需要:可以自己加在name上,所以这里也不用改了哈。
from jetcache.
@areyouok 连接符可以有?作为配置项?
from jetcache.
楼上我说过了,name和key之间并没有下划线连接。不过昨天说的不是很全面。详细说是这样的:
1、name会作为key前缀,拼接时和key之间没有任何连接符,area不会作为key前缀。所以只要自己指定name就不会有任何问题。
2、如果没有指定name,自动生成的name会包含area、类名、方法名、参数,使用了各种连接符,有下划线、点,但是name的key之间仍然没有连接符。如果需要定制,不是指定一个连接符就可以,而是需要用户自己给出一个name生成器,这个真的需要么?如果用户关心这方面的监控,手工指定name是不是更好?
from jetcache.
①area不会作为前缀我知道。这里有一个问题,我想楼主的问题是不是把area看作redis里的db0~db15来对待的?有点类似Tair的namespace?不知道我理解的对不对。@areyouok 黄兄对area在redis中是怎么处理的?
②就是说name+key的连接方式,其实很多用户去写代码的时候不会或者忘记自己加个连接符,亦或者加了连接符,每个coder用的连接符可能不一样。这样规范性上来说,不如直接给个配置项配置连接符。省的用户去@cached注解上手动指定。
from jetcache.
1、就是相当于tair的不同集群(或不同namespace),之前我们的同一个应用需要连好几个tair的,不同的tair配置是不一样的,所以需要area加以区分。一般你没有需要,这个area就不用设置了,默认的就好。
2、name作为key前缀的一部分,首先我考虑的是唯一性问题,这是为了防止key冲突,所以之前生成的name又长又不好看,也没有考虑过分隔符的问题。如果要改好像只能允许用户自己定制一个name生成器(默认用之前的生成方式,以免用户升级jetcache以后出现key前缀变更造成兼容性问题),能用到这个地步的都是高级用户了。
这个我改一下吧,预留出指定生成器的接口。
from jetcache.
有了:
c729e7f
from jetcache.
这效率,杠杠的:+1:默认的generator能不能接受一个连接符参数?
from jetcache.
你看下代码就知道了,不能简单的加个连接符参数。
有点遗漏,还需要再改一下。之前我的说法有问题,area确实作为key前缀了,哈哈。现在杯具了,有点不好改。
from jetcache.
又提交了一个,应该是改好了。
from jetcache.
@areyouok 这改动是不是有点重了,并且还是需要开发者通过代码来实现自定义连接符而不是通过配置。
我的分支里是这样改的:
JetCacheProperties
和GlobalCacheConfig.java
里增加keyDelimiter
和defaultArea
两个配置参数,可以通过配置文件来定义这两个参数的值。
在JetCacheAutoConfiguration
中将配置文件中的keyDelimiter
和defaultArea
赋值给_globalCacheConfig
。
然后就是修改CacheContext
中生成cache相关的代码了:
private Cache createCacheByCachedConfig(CachedAnnoConfig ac, Method method, String[] hiddenPackages) {
String area = ac.getArea();
if (CacheConsts.DEFAULT_AREA.equalsIgnoreCase(area) && globalCacheConfig.getDefaultArea() != null) {
area = globalCacheConfig.getDefaultArea().trim(); // 使用配置文件中的area
}
}
public Cache __createOrGetCache(CachedAnnoConfig cachedAnnoConfig, String area, String cacheName) {
// 使用配置文件中的连接符
String fullCacheName = area + (globalCacheConfig.getKeyDelimiter() == null ? "_" : globalCacheConfig.getKeyDelimiter()) + cacheName;
}
protected Cache buildRemote(CachedAnnoConfig cachedAnnoConfig, String area, String cacheName) {
// 使用配置文件中的连接符
String keyPrefix = cacheBuilder.getConfig().getKeyPrefix() != null ? cacheBuilder.getConfig().getKeyPrefix() : "";
keyPrefix += cacheName;
keyPrefix += globalCacheConfig.getKeyDelimiter() != null ? globalCacheConfig.getKeyDelimiter() : "_";
cacheBuilder.setKeyPrefix(keyPrefix);
}
配置文件:
jetcache:
statIntervalMinutes: 15
hiddenPackages: cn.cytong
keyDelimiter: :
defaultArea: booking
对于redis缓存,生成的key格式就是:booking:{cacheName}:{key}
格式了。
from jetcache.
大概就是这个意思,不过area不应该作为key的前缀,另外defaulyArea不应该在这里配置,而应该在caches的配置里有个名叫default的Cache
from jetcache.
说错了,jetcache对应的是local和remote下的子项名叫default
from jetcache.
@chenchi2038
你的改动主要是定制了area和cache name之间的连接符,以及并且可以定制default area的名字(我觉得default area的名字还要定制是很奇怪的,你觉得呢,写文档的时候要怎么跟人解释这个事情T_T)。
但是area本来就不该作为key的一部分(之前我把area放到key里是失策了),况且默认生成的cache name可读性也很不好比如c.a.j.a.m.ClassUtilTest$C1.foo2(Lc.a.j.a.m.ClassUtilTest$I1;)
这样的,也许有人想要只用类名+方法名作为自动生成的cache name,所以既然定制就灵活点。使用上也不是很复杂,只要在业务程序的App Class里面加个bean就好了,不用改jetcache本身,并不比配置麻烦多少。最简单的情况就是这样:
@Bean
public SpringConfigProvider springConfigProvider() {
return new SpringConfigProvider(){
public CacheNameGenerator createCacheNameGenerator(String[] hiddenPackages){
return new DefaultCacheNameGenerator(){};
}
};
}
这里返回了一个匿名内部类覆盖了DefaultCacheNameGenerator,然后在当前版本的CacheContext中,只要不是DefaultCacheNameGenerator本身就不会把area加到key里面了。当然你还可以覆盖方法实现自己的cache name自动生成。
SpringConfigProvider这个类本来就是用来覆盖的,也许使用者想要定制自己的key生成器,或者encoder/decoder都可以通过这样的方式来实现。
from jetcache.
我增加了一个选项,areaInCacheName,为了保持兼容,默认是true。把它设置为false之后,area就不会出现在key前缀中,因此也不需要配置连接符了。
配合新的Encoder/Decoder的useIdentityNumber选项,以后使用jetcache和不使用jetcache的程序可以读写同一个key。
from jetcache.
Related Issues (20)
- 文档有一处,编辑错误 HOT 1
- 配置了broadcastChannel ,syncLocal = true jvm缓存不失效 HOT 3
- cause by java.lang.NullPointerException: no decoder for identity number:-153049664 HOT 11
- 自定义项目my-jetcache-starter包后,jetcache无法使用starter包中的默认配置进行初始化 HOT 4
- SpringBoot3.2项目中@Cached注解key属性不支持参数名 HOT 2
- 当redis某个节点发生故障无法连接,导致项目无法启动
- 希望可以支持r2dbc,可以支持Reactor缓存
- spring项目引入jetcache启动报错 HOT 2
- 如何通过redis.lettuce连接带证书的redis?(redis非集群,HA模式的) HOT 1
- 反序列化异常 HOT 1
- redisson缓存通知,是否有规划增加redis stream方式 HOT 1
- 缓存一致性问题 HOT 1
- JedisCluster Pipeline 的支持? HOT 13
- @Cached、@CacheUpdate中的key、value是否像postCondition 、condition可以使用SpEL访问到#result对象? HOT 4
- Cached是否可以一次设置多个key? HOT 2
- AbstractCacheTest.penetrationProtectTest flaky
- api模式下 key过期时间配置
- @Cached注解使用key SpEL表达式,注解作用在接口上时失效。 HOT 9
- 请求一下,使用LinkedHashMap的方法存储本地缓存不失效,并且在使用清除本地缓存方法中,写锁没有释放 HOT 8
- 如何自定义 RedisCache ?
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from jetcache.