0. 引言
在實(shí)際應(yīng)用中,并不是單一的使用本地緩存或者redis,更多是組合使用來(lái)滿足不同的業(yè)務(wù)場(chǎng)景,于是如何優(yōu)雅的組合本地緩存和遠(yuǎn)程緩存就成了我們要研究的問題,而這一點(diǎn),阿里開源的jetcache組件幫我們實(shí)現(xiàn)了
1. jetcache簡(jiǎn)介
jetcache是阿里開源的基于java開發(fā)的緩存框架,支持多種緩存類型:本地緩存、分布式緩存、多級(jí)緩存。能夠滿足不同業(yè)務(wù)場(chǎng)景的緩存需求。
jetcache具有上手簡(jiǎn)單、性能高效、拓展性強(qiáng)的特點(diǎn)。支持緩存預(yù)熱 、緩存key前綴等功能。結(jié)合spring-cache使用,可以實(shí)現(xiàn)十分優(yōu)雅的緩存類型切換
2. jetcache使用
1、引入依賴,這里我們使用sringboot項(xiàng)目框架,同時(shí)使用redis作為遠(yuǎn)程緩存。于是我們引入jetcache-starter-redis依賴,這里我的springboot版本為2.6.13
如果是非springboot項(xiàng)目可以參考官網(wǎng)說(shuō)明配置
com.alicp.jetcache jetcache-starter-redis 2.7.0 redis.clients jedis 4.3.1
對(duì)應(yīng)的版本說(shuō)明如下:springboot與jetcache版本關(guān)系
2、修改配置文件,配置redis地址和線程數(shù)
jetcache: #統(tǒng)計(jì)間隔,0表示不統(tǒng)計(jì),開啟后定期在控制臺(tái)輸出緩存信息 statIntervalMinutes:15 #是否把cacheName作為遠(yuǎn)程緩存key前綴 areaInCacheName:false #本地緩存配置 local: default:#default表示全部生效,也可以指定某個(gè)cacheName #本地緩存類型,其他可選:caffeine/linkedhashmap type:linkedhashmap keyConvertor:fastjson #遠(yuǎn)程緩存配置 remote: default:#default表示全部生效,也可以指定某個(gè)cacheName type:redis #key轉(zhuǎn)換器方式n keyConvertor:fastjson broadcastChannel:projectA #redis序列化方式 valueEncoder:java valueDecoder:java #redis線程池 poolConfig: minIdle:5 maxIdle:20 maxTotal:50 #redis地址與端口 host:127.0.0.1 port:6379
更詳細(xì)的參數(shù)配置
3、啟動(dòng)類添加注解@EnableCreateCacheAnnotation,開啟緩存,添加@EnableMethodCache(basePackages = "com.example.jetcachedemo")注解,配置緩存方法掃描路徑
4、使用緩存可以通過三種方式:
方式一(推薦)AOP模式:通過@Cached,@CacheUpdate,@CacheInvalidate注解
@RestController @RequestMapping("user") publicclassUserController{ @GetMapping("getRemote") @Cached(name="userCache:",key="#id",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.REMOTE) publicUsergetRemote(Longid){ //直接新建用戶,模擬從數(shù)據(jù)庫(kù)獲取數(shù)據(jù) Useruser=newUser(); user.setId(id); user.setName("用戶remote"+id); user.setAge(23); user.setSex(1); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @GetMapping("getLocal") @Cached(name="userCache:",key="#id",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.LOCAL) publicUsergetLocal(Longid){ //直接新建用戶,模擬從數(shù)據(jù)庫(kù)獲取數(shù)據(jù) Useruser=newUser(); user.setId(id); user.setName("用戶local"+id); user.setAge(23); user.setSex(1); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @GetMapping("getBoth") @Cached(name="userCache:",key="#id",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.BOTH) publicUsergetBoth(Longid){ //直接新建用戶,模擬從數(shù)據(jù)庫(kù)獲取數(shù)據(jù) Useruser=newUser(); user.setId(id); user.setName("用戶both"+id); user.setAge(23); user.setSex(1); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @PostMapping("updateUser") @CacheUpdate(name="userCache:",key="#user.id",value="#user") publicBooleanupdateUser(@RequestBodyUseruser){ //TODO更新數(shù)據(jù)庫(kù) returntrue; } @PostMapping("deleteUser") @CacheInvalidate(name="userCache:",key="#id") publicBooleandeleteUser(Longid){ //TODO從數(shù)據(jù)庫(kù)刪除 returntrue; } }
這里要注意實(shí)體類User一定要實(shí)現(xiàn)序列化,即聲明Serializable
@Data publicclassUserimplementsSerializable{ privateLongid; privateStringname; privateIntegerage; privateIntegersex; }
方式二 API模式:通過@CreateCache,注:在jetcache 2.7 版本CreateCache注解已廢棄,不推薦使用
@RestController @RequestMapping("user2") publicclassUser2Controller{ @CreateCache(name="userCache:",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.BOTH) privateCacheuserCache; @GetMapping("get") publicUserget(Longid){ if(userCache.get(id)!=null){ return(User)userCache.get(id); } Useruser=newUser(); user.setId(id); user.setName("用戶both"+id); user.setAge(23); user.setSex(1); userCache.put(id,user); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @PostMapping("updateUser") publicBooleanupdateUser(@RequestBodyUseruser){ //TODO更新數(shù)據(jù)庫(kù) userCache.put(user.getId(),user); returntrue; } @PostMapping("deleteUser") publicBooleandeleteUser(Longid){ //TODO從數(shù)據(jù)庫(kù)刪除 userCache.remove(id); returntrue; } }
方式三 高級(jí)API模式:通過CacheManager,2.7 版本才可使用
(1)添加依賴
com.alibaba fastjson 2.0.25
(2)書寫配置類
@Configuration publicclassJetcacheConfig{ @Autowired privateCacheManagercacheManager; privateCacheuserCache; @PostConstruct publicvoidinit(){ QuickConfigqc=QuickConfig.newBuilder("userCache:") .expire(Duration.ofSeconds(3600)) .cacheType(CacheType.BOTH) //本地緩存更新后,將在所有的節(jié)點(diǎn)中刪除緩存,以保持強(qiáng)一致性 .syncLocal(false) .build(); userCache=cacheManager.getOrCreateCache(qc); } @Bean publicCache getUserCache(){ returnuserCache; } }
(3)調(diào)用代碼
@RestController @RequestMapping("user3") publicclassUser3Controller{ @Autowired JetcacheConfigjetcacheConfig; @Autowired privateCacheuserCache; @GetMapping("get") publicUserget(Longid){ if(userCache.get(id)!=null){ return(User)userCache.get(id); } Useruser=newUser(); user.setId(id); user.setName("用戶both"+id); user.setAge(23); user.setSex(1); userCache.put(id,user); System.out.println("第一次獲取數(shù)據(jù),未走緩存:"+id); returnuser; } @PostMapping("updateUser") publicBooleanupdateUser(@RequestBodyUseruser){ //TODO更新數(shù)據(jù)庫(kù) userCache.put(user.getId(),user); returntrue; } @PostMapping("deleteUser") publicBooleandeleteUser(Longid){ //TODO從數(shù)據(jù)庫(kù)刪除 userCache.remove(id); returntrue; } }
多級(jí)緩存的形式,會(huì)先從本地緩存獲取數(shù)據(jù),本地獲取不到會(huì)從遠(yuǎn)程緩存獲取
5、啟動(dòng)redis,啟動(dòng)演示項(xiàng)目
注意,如果啟動(dòng)出現(xiàn)NoClassDefFoundError: redis/clients/util/Pool或NoClassDefFoundError: redis/clients/jedis/UnifiedJedis報(bào)錯(cuò),說(shuō)明springboot與jetcache版本不一致,對(duì)應(yīng)關(guān)系可參考上述第一步中的說(shuō)明 同時(shí)如果使用的是jetcache2.7.x版本,因?yàn)樵摪姹局杏衘edis包的依賴,需要額外添加如下依賴,或者將jetcache版本將至2.6.5以下
redis.clients jedis 4.3.1
3. 測(cè)試
3.1 方式一測(cè)試
1、訪問localhost:8088/user/getRemote?id=1
因?yàn)榕渲玫氖沁h(yuǎn)程緩存,在redis中也能看到對(duì)應(yīng)的key
2、訪問localhost:8088/user/getLocal?id=1,這個(gè)方法是從本地緩存獲取的,現(xiàn)在只有遠(yuǎn)程緩存上有數(shù)據(jù),我們調(diào)用發(fā)現(xiàn)緩存數(shù)據(jù)還是拿到了,這說(shuō)明當(dāng)我們?cè)谂渲梦募信渲昧吮镜鼐彺婧瓦h(yuǎn)程緩存后,方式一中本地緩存和遠(yuǎn)程緩存會(huì)自動(dòng)相互調(diào)用
比如本地緩存有這個(gè)key,redis中沒有,通過遠(yuǎn)程緩存方式訪問時(shí),會(huì)先從redis獲取,如果沒有會(huì)自動(dòng)獲取本地緩存,但是數(shù)據(jù)還是存儲(chǔ)在本地緩存,并不會(huì)同步到redis上,這樣更加靈活的實(shí)現(xiàn)了多級(jí)緩存架構(gòu)
3.2 方式二測(cè)試
1、再測(cè)試下CreateCache的形式:localhost:8088/user2/get?id=4
正常獲取了,并且redis中也有了對(duì)應(yīng)的值
而當(dāng)我們把緩存方式更改為L(zhǎng)OCAL后,再訪問localhost:8088/user2/get?id=5
@CreateCache(name="userCache:",expire=3600,timeUnit=TimeUnit.SECONDS,cacheType=CacheType.LOCAL)
會(huì)發(fā)現(xiàn)redis中就沒有對(duì)應(yīng)緩存了,只在本地緩存存在,說(shuō)明我們指定本地緩存的形式成功了
3.3 方式三測(cè)試
1、調(diào)用localhost:8088/user3/get?id=11
redis中緩存設(shè)置成功!
4. 常見報(bào)錯(cuò)
1、 ClassNotFoundException: com.alibaba.fastjson.JSON 解決:添加依賴
com.alibaba fastjson 2.0.25
2、NoClassDefFoundError: redis/clients/jedis/UnifiedJedis 解決: 添加依賴
redis.clients jedis 4.3.1
或者將jetcache版本降低至2.6.5以下
演示源碼
https://gitee.com/wuhanxue/wu_study/tree/master/demo/jetcache-demo
審核編輯:湯梓紅
-
JAVA
+關(guān)注
關(guān)注
19文章
2966瀏覽量
104702 -
緩存
+關(guān)注
關(guān)注
1文章
239瀏覽量
26671 -
開源
+關(guān)注
關(guān)注
3文章
3309瀏覽量
42471 -
spring
+關(guān)注
關(guān)注
0文章
340瀏覽量
14338 -
Redis
+關(guān)注
關(guān)注
0文章
374瀏覽量
10871
原文標(biāo)題:jetcache:阿里這款多級(jí)緩存框架一定要掌握
文章出處:【微信號(hào):magedu-Linux,微信公眾號(hào):馬哥Linux運(yùn)維】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論